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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
/* This file is part of the dynarmic project.
* Copyright (c) 2016 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
#include <initializer_list>
#include "common/common_types.h"
#include "frontend/arm_types.h"
#include "frontend/ir/basic_block.h"
#include "frontend/ir/opcodes.h"
#include "frontend/ir/terminal.h"
#include "frontend/ir/value.h"
// ARM JIT Microinstruction Intermediate Representation
//
// This intermediate representation is an SSA IR. It is designed primarily for analysis,
// though it can be lowered into a reduced form for interpretation. Each IR node (Value)
// is a microinstruction of an idealised ARM CPU. The choice of microinstructions is made
// not based on any existing microarchitecture but on ease of implementation.
namespace Dynarmic {
namespace IR {
/**
* Convenience class to construct a basic block of the intermediate representation.
* `block` is the resulting block.
* The user of this class updates `current_location` as appropriate.
*/
class IREmitter {
public:
explicit IREmitter(Arm::LocationDescriptor descriptor) : block(descriptor), current_location(descriptor) {}
Block block;
Arm::LocationDescriptor current_location;
struct ResultAndCarry {
Value result;
Value carry;
};
struct ResultAndCarryAndOverflow {
Value result;
Value carry;
Value overflow;
};
void Unimplemented();
u32 PC();
u32 AlignPC(size_t alignment);
Value Imm1(bool value);
Value Imm8(u8 value);
Value Imm32(u32 value);
Value GetRegister(Arm::Reg source_reg);
Value GetExtendedRegister(Arm::ExtReg source_reg);
void SetRegister(const Arm::Reg dest_reg, const Value& value);
void SetExtendedRegister(const Arm::ExtReg dest_reg, const Value& value);
void ALUWritePC(const Value& value);
void BranchWritePC(const Value& value);
void BXWritePC(const Value& value);
void LoadWritePC(const Value& value);
void CallSupervisor(const Value& value);
void PushRSB(const Arm::LocationDescriptor& return_location);
Value GetCpsr();
void SetCpsr(const Value& value);
Value GetCFlag();
void SetNFlag(const Value& value);
void SetZFlag(const Value& value);
void SetCFlag(const Value& value);
void SetVFlag(const Value& value);
void OrQFlag(const Value& value);
Value GetFpscr();
void SetFpscr(const Value& new_fpscr);
Value GetFpscrNZCV();
void SetFpscrNZCV(const Value& new_fpscr_nzcv);
Value Pack2x32To1x64(const Value& lo, const Value& hi);
Value LeastSignificantWord(const Value& value);
ResultAndCarry MostSignificantWord(const Value& value);
Value LeastSignificantHalf(const Value& value);
Value LeastSignificantByte(const Value& value);
Value MostSignificantBit(const Value& value);
Value IsZero(const Value& value);
Value IsZero64(const Value& value);
ResultAndCarry LogicalShiftLeft(const Value& value_in, const Value& shift_amount, const Value& carry_in);
ResultAndCarry LogicalShiftRight(const Value& value_in, const Value& shift_amount, const Value& carry_in);
Value LogicalShiftRight64(const Value& value_in, const Value& shift_amount);
ResultAndCarry ArithmeticShiftRight(const Value& value_in, const Value& shift_amount, const Value& carry_in);
ResultAndCarry RotateRight(const Value& value_in, const Value& shift_amount, const Value& carry_in);
ResultAndCarry RotateRightExtended(const Value& value_in, const Value& carry_in);
ResultAndCarryAndOverflow AddWithCarry(const Value& a, const Value& b, const Value& carry_in);
Value Add(const Value& a, const Value& b);
Value Add64(const Value& a, const Value& b);
ResultAndCarryAndOverflow SubWithCarry(const Value& a, const Value& b, const Value& carry_in);
Value Sub(const Value& a, const Value& b);
Value Sub64(const Value& a, const Value& b);
Value Mul(const Value& a, const Value& b);
Value Mul64(const Value& a, const Value& b);
Value And(const Value& a, const Value& b);
Value Eor(const Value& a, const Value& b);
Value Or(const Value& a, const Value& b);
Value Not(const Value& a);
Value SignExtendWordToLong(const Value& a);
Value SignExtendHalfToWord(const Value& a);
Value SignExtendByteToWord(const Value& a);
Value ZeroExtendWordToLong(const Value& a);
Value ZeroExtendHalfToWord(const Value& a);
Value ZeroExtendByteToWord(const Value& a);
Value ByteReverseWord(const Value& a);
Value ByteReverseHalf(const Value& a);
Value ByteReverseDual(const Value& a);
Value PackedSaturatedAddU8(const Value& a, const Value& b);
Value PackedSaturatedAddS8(const Value& a, const Value& b);
Value PackedSaturatedSubU8(const Value& a, const Value& b);
Value PackedSaturatedSubS8(const Value& a, const Value& b);
Value PackedSaturatedAddU16(const Value& a, const Value& b);
Value PackedSaturatedAddS16(const Value& a, const Value& b);
Value PackedSaturatedSubU16(const Value& a, const Value& b);
Value PackedSaturatedSubS16(const Value& a, const Value& b);
Value TransferToFP32(const Value& a);
Value TransferToFP64(const Value& a);
Value TransferFromFP32(const Value& a);
Value TransferFromFP64(const Value& a);
Value FPAbs32(const Value& a);
Value FPAbs64(const Value& a);
Value FPAdd32(const Value& a, const Value& b, bool fpscr_controlled);
Value FPAdd64(const Value& a, const Value& b, bool fpscr_controlled);
Value FPDiv32(const Value& a, const Value& b, bool fpscr_controlled);
Value FPDiv64(const Value& a, const Value& b, bool fpscr_controlled);
Value FPMul32(const Value& a, const Value& b, bool fpscr_controlled);
Value FPMul64(const Value& a, const Value& b, bool fpscr_controlled);
Value FPNeg32(const Value& a);
Value FPNeg64(const Value& a);
Value FPSqrt32(const Value& a);
Value FPSqrt64(const Value& a);
Value FPSub32(const Value& a, const Value& b, bool fpscr_controlled);
Value FPSub64(const Value& a, const Value& b, bool fpscr_controlled);
Value FPDoubleToSingle(const Value& a, bool fpscr_controlled);
Value FPSingleToDouble(const Value& a, bool fpscr_controlled);
Value FPSingleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled);
Value FPSingleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled);
Value FPDoubleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled);
Value FPDoubleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled);
Value FPS32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled);
Value FPU32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled);
Value FPS32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled);
Value FPU32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled);
void ClearExclusive();
void SetExclusive(const Value& vaddr, size_t byte_size);
Value ReadMemory8(const Value& vaddr);
Value ReadMemory16(const Value& vaddr);
Value ReadMemory32(const Value& vaddr);
Value ReadMemory64(const Value& vaddr);
void WriteMemory8(const Value& vaddr, const Value& value);
void WriteMemory16(const Value& vaddr, const Value& value);
void WriteMemory32(const Value& vaddr, const Value& value);
void WriteMemory64(const Value& vaddr, const Value& value);
Value ExclusiveWriteMemory8(const Value& vaddr, const Value& value);
Value ExclusiveWriteMemory16(const Value& vaddr, const Value& value);
Value ExclusiveWriteMemory32(const Value& vaddr, const Value& value);
Value ExclusiveWriteMemory64(const Value& vaddr, const Value& value_lo, const Value& value_hi);
void Breakpoint();
void SetTerm(const Terminal& terminal);
private:
Value Inst(Opcode op, std::initializer_list<Value> args);
};
} // namespace IR
} // namespace Dynarmic
|