1 /* This file is part of the dynarmic project.
2  * Copyright (c) 2016 MerryMage
3  * SPDX-License-Identifier: 0BSD
4  */
5 
6 #include "frontend/A32/translate/impl/translate_arm.h"
7 
8 namespace Dynarmic::A32 {
9 
Rotate(A32::IREmitter & ir,Reg m,SignExtendRotation rotate)10 static IR::U32 Rotate(A32::IREmitter& ir, Reg m, SignExtendRotation rotate) {
11     const u8 rotate_by = static_cast<u8>(static_cast<size_t>(rotate) * 8);
12     return ir.RotateRight(ir.GetRegister(m), ir.Imm8(rotate_by), ir.Imm1(0)).result;
13 }
14 
15 // SXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
arm_SXTAB(Cond cond,Reg n,Reg d,SignExtendRotation rotate,Reg m)16 bool ArmTranslatorVisitor::arm_SXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
17     if (d == Reg::PC || m == Reg::PC) {
18         return UnpredictableInstruction();
19     }
20 
21     if (!ConditionPassed(cond)) {
22         return true;
23     }
24 
25     const auto rotated = Rotate(ir, m, rotate);
26     const auto reg_n = ir.GetRegister(n);
27     const auto result = ir.Add(reg_n, ir.SignExtendByteToWord(ir.LeastSignificantByte(rotated)));
28 
29     ir.SetRegister(d, result);
30     return true;
31 }
32 
33 // SXTAB16<c> <Rd>, <Rn>, <Rm>{, <rotation>}
arm_SXTAB16(Cond cond,Reg n,Reg d,SignExtendRotation rotate,Reg m)34 bool ArmTranslatorVisitor::arm_SXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
35     if (d == Reg::PC || m == Reg::PC) {
36         return UnpredictableInstruction();
37     }
38 
39     if (!ConditionPassed(cond)) {
40         return true;
41     }
42 
43     const auto rotated = Rotate(ir, m, rotate);
44     const auto low_byte = ir.And(rotated, ir.Imm32(0x00FF00FF));
45     const auto sign_bit = ir.And(rotated, ir.Imm32(0x00800080));
46     const auto addend = ir.Or(low_byte, ir.Mul(sign_bit, ir.Imm32(0x1FE)));
47     const auto result = ir.PackedAddU16(addend, ir.GetRegister(n)).result;
48 
49     ir.SetRegister(d, result);
50     return true;
51 }
52 
53 // SXTAH<c> <Rd>, <Rn>, <Rm>{, <rotation>}
arm_SXTAH(Cond cond,Reg n,Reg d,SignExtendRotation rotate,Reg m)54 bool ArmTranslatorVisitor::arm_SXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
55     if (d == Reg::PC || m == Reg::PC) {
56         return UnpredictableInstruction();
57     }
58 
59     if (!ConditionPassed(cond)) {
60         return true;
61     }
62 
63     const auto rotated = Rotate(ir, m, rotate);
64     const auto reg_n = ir.GetRegister(n);
65     const auto result = ir.Add(reg_n, ir.SignExtendHalfToWord(ir.LeastSignificantHalf(rotated)));
66 
67     ir.SetRegister(d, result);
68     return true;
69 }
70 
71 // SXTB<c> <Rd>, <Rm>{, <rotation>}
arm_SXTB(Cond cond,Reg d,SignExtendRotation rotate,Reg m)72 bool ArmTranslatorVisitor::arm_SXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
73     if (d == Reg::PC || m == Reg::PC) {
74         return UnpredictableInstruction();
75     }
76 
77     if (!ConditionPassed(cond)) {
78         return true;
79     }
80 
81     const auto rotated = Rotate(ir, m, rotate);
82     const auto result = ir.SignExtendByteToWord(ir.LeastSignificantByte(rotated));
83 
84     ir.SetRegister(d, result);
85     return true;
86 }
87 
88 // SXTB16<c> <Rd>, <Rm>{, <rotation>}
arm_SXTB16(Cond cond,Reg d,SignExtendRotation rotate,Reg m)89 bool ArmTranslatorVisitor::arm_SXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
90     if (d == Reg::PC || m == Reg::PC) {
91         return UnpredictableInstruction();
92     }
93 
94     if (!ConditionPassed(cond)) {
95         return true;
96     }
97 
98     const auto rotated = Rotate(ir, m, rotate);
99     const auto low_byte = ir.And(rotated, ir.Imm32(0x00FF00FF));
100     const auto sign_bit = ir.And(rotated, ir.Imm32(0x00800080));
101     const auto result = ir.Or(low_byte, ir.Mul(sign_bit, ir.Imm32(0x1FE)));
102 
103     ir.SetRegister(d, result);
104     return true;
105 }
106 
107 // SXTH<c> <Rd>, <Rm>{, <rotation>}
arm_SXTH(Cond cond,Reg d,SignExtendRotation rotate,Reg m)108 bool ArmTranslatorVisitor::arm_SXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
109     if (d == Reg::PC || m == Reg::PC) {
110         return UnpredictableInstruction();
111     }
112 
113     if (!ConditionPassed(cond)) {
114         return true;
115     }
116 
117     const auto rotated = Rotate(ir, m, rotate);
118     const auto result = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(rotated));
119 
120     ir.SetRegister(d, result);
121     return true;
122 }
123 
124 // UXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
arm_UXTAB(Cond cond,Reg n,Reg d,SignExtendRotation rotate,Reg m)125 bool ArmTranslatorVisitor::arm_UXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
126     if (d == Reg::PC || m == Reg::PC) {
127         return UnpredictableInstruction();
128     }
129 
130     if (!ConditionPassed(cond)) {
131         return true;
132     }
133 
134     const auto rotated = Rotate(ir, m, rotate);
135     const auto reg_n = ir.GetRegister(n);
136     const auto result = ir.Add(reg_n, ir.ZeroExtendByteToWord(ir.LeastSignificantByte(rotated)));
137 
138     ir.SetRegister(d, result);
139     return true;
140 }
141 
142 // UXTAB16<c> <Rd>, <Rn>, <Rm>{, <rotation>}
arm_UXTAB16(Cond cond,Reg n,Reg d,SignExtendRotation rotate,Reg m)143 bool ArmTranslatorVisitor::arm_UXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
144     if (d == Reg::PC || m == Reg::PC || n == Reg::PC) {
145         return UnpredictableInstruction();
146     }
147 
148     if (!ConditionPassed(cond)) {
149         return true;
150     }
151 
152     const auto rotated = Rotate(ir, m, rotate);
153     auto result = ir.And(rotated, ir.Imm32(0x00FF00FF));
154     const auto reg_n = ir.GetRegister(n);
155     result = ir.PackedAddU16(reg_n, result).result;
156 
157     ir.SetRegister(d, result);
158     return true;
159 }
160 
161 // UXTAH<c> <Rd>, <Rn>, <Rm>{, <rotation>}
arm_UXTAH(Cond cond,Reg n,Reg d,SignExtendRotation rotate,Reg m)162 bool ArmTranslatorVisitor::arm_UXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
163     if (d == Reg::PC || m == Reg::PC) {
164         return UnpredictableInstruction();
165     }
166 
167     if (!ConditionPassed(cond)) {
168         return true;
169     }
170 
171     const auto rotated = Rotate(ir, m, rotate);
172     const auto reg_n = ir.GetRegister(n);
173     const auto result = ir.Add(reg_n, ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(rotated)));
174 
175     ir.SetRegister(d, result);
176     return true;
177 }
178 
179 // UXTB<c> <Rd>, <Rm>{, <rotation>}
arm_UXTB(Cond cond,Reg d,SignExtendRotation rotate,Reg m)180 bool ArmTranslatorVisitor::arm_UXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
181     if (d == Reg::PC || m == Reg::PC) {
182         return UnpredictableInstruction();
183     }
184 
185     if (!ConditionPassed(cond)) {
186         return true;
187     }
188 
189     const auto rotated = Rotate(ir, m, rotate);
190     const auto result = ir.ZeroExtendByteToWord(ir.LeastSignificantByte(rotated));
191     ir.SetRegister(d, result);
192     return true;
193 }
194 
195 // UXTB16<c> <Rd>, <Rm>{, <rotation>}
arm_UXTB16(Cond cond,Reg d,SignExtendRotation rotate,Reg m)196 bool ArmTranslatorVisitor::arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
197     if (d == Reg::PC || m == Reg::PC) {
198         return UnpredictableInstruction();
199     }
200 
201     if (!ConditionPassed(cond)) {
202         return true;
203     }
204 
205     const auto rotated = Rotate(ir, m, rotate);
206     const auto result = ir.And(rotated, ir.Imm32(0x00FF00FF));
207 
208     ir.SetRegister(d, result);
209     return true;
210 }
211 
212 // UXTH<c> <Rd>, <Rm>{, <rotation>}
arm_UXTH(Cond cond,Reg d,SignExtendRotation rotate,Reg m)213 bool ArmTranslatorVisitor::arm_UXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
214     if (d == Reg::PC || m == Reg::PC) {
215         return UnpredictableInstruction();
216     }
217 
218     if (!ConditionPassed(cond)) {
219         return true;
220     }
221 
222     const auto rotated = Rotate(ir, m, rotate);
223     const auto result = ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(rotated));
224 
225     ir.SetRegister(d, result);
226     return true;
227 }
228 
229 } // namespace Dynarmic::A32
230