20 template <
typename TDest,
typename TArg0,
typename TArg1>
22 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm,
24 auto n = ictx.cpua.ReadRegister(rn.Get());
25 auto m = ictx.cpua.ReadRegister(rm.Get());
26 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
27 const auto shift_val = Alu32::Shift_C(m, shift_res.type, shift_res.value,
28 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
29 const auto &shifted = shift_val.result;
31 const u32 result = Alu32::EOR(n, shifted);
33 OpResult{result, shift_val.carry_out, (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
35 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
36 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
37 PostExecAdvancePcAndIt::Call(ictx, iflags);
38 return Ok(kNoInstrExecFlags);
49 template <
typename TDest,
typename TArg0,
typename TArg1>
51 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm,
53 auto n = ictx.cpua.ReadRegister(rn.Get());
54 auto m = ictx.cpua.ReadRegister(rm.Get());
55 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
56 const auto shift_val = Alu32::Shift_C(m, shift_res.type, shift_res.value,
57 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
58 const auto &shifted = shift_val.result;
60 const u32 result = Alu32::OR(n, shifted);
62 OpResult{result, shift_val.carry_out, (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
63 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
64 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
65 PostExecAdvancePcAndIt::Call(ictx, iflags);
66 return Ok(kNoInstrExecFlags);
77 template <
typename TDest,
typename TArg0,
typename TArg1>
79 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm,
81 auto n = ictx.cpua.ReadRegister(rn.Get());
82 auto m = ictx.cpua.ReadRegister(rm.Get());
83 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
84 const auto shift_val = Alu32::Shift_C(m, shift_res.type, shift_res.value,
85 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
86 const auto &shifted = shift_val.result;
88 const u32 result = Alu32::AND(n, shifted);
90 OpResult{result, shift_val.carry_out, (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
91 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
92 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
93 PostExecAdvancePcAndIt::Call(ictx, iflags);
94 return Ok(kNoInstrExecFlags);
105 template <
typename TDest,
typename TArg0,
typename TArg1>
107 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm,
109 auto n = ictx.cpua.ReadRegister(rn.Get());
110 auto m = ictx.cpua.ReadRegister(rm.Get());
111 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
112 const auto shift_val = Alu32::Shift_C(m, shift_res.type, shift_res.value,
113 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
114 const auto &shifted = shift_val.result;
116 const u32 result = Alu32::AND(n, ~shifted);
118 OpResult{result, shift_val.carry_out, (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
119 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
120 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
121 PostExecAdvancePcAndIt::Call(ictx, iflags);
122 return Ok(kNoInstrExecFlags);
133 template <
typename TDest,
typename TArg0,
typename TArg1>
135 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm,
137 auto n = ictx.cpua.ReadRegister(rn.Get());
138 auto m = ictx.cpua.ReadRegister(rm.Get());
139 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
140 const auto shifted = Alu32::Shift(m, shift_res.type, shift_res.value,
141 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
143 Alu32::AddWithCarry(n, ~shifted, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
145 const auto op_res =
OpResult{result.value, result.carry_out, result.overflow};
146 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
147 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
148 PostExecAdvancePcAndIt::Call(ictx, iflags);
149 return Ok(kNoInstrExecFlags);
160 template <
typename TDest,
typename TArg0,
typename TArg1>
162 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm,
164 auto n = ictx.cpua.ReadRegister(rn.Get());
165 auto m = ictx.cpua.ReadRegister(rm.Get());
166 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
167 const auto shifted = Alu32::Shift(m, shift_res.type, shift_res.value,
168 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
169 const auto result = Alu32::AddWithCarry(n, ~shifted,
true);
170 const auto op_res =
OpResult{result.value, result.carry_out, result.overflow};
171 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
172 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
173 PostExecAdvancePcAndIt::Call(ictx, iflags);
174 return Ok(kNoInstrExecFlags);
185 template <
typename TDest,
typename TArg0,
typename TArg1>
187 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm,
189 auto n = ictx.cpua.ReadRegister(rn.Get());
190 auto m = ictx.cpua.ReadRegister(rm.Get());
191 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
192 const auto shifted = Alu32::Shift(m, shift_res.type, shift_res.value,
193 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
194 const auto result = Alu32::AddWithCarry(~n, shifted,
true);
195 const auto op_res =
OpResult{result.value, result.carry_out, result.overflow};
196 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
197 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
198 PostExecAdvancePcAndIt::Call(ictx, iflags);
199 return Ok(kNoInstrExecFlags);
209 template <
typename TDest,
typename TArg0,
typename TArg1>
211 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm,
213 auto n = ictx.cpua.ReadRegister(rn.Get());
214 auto m = ictx.cpua.ReadRegister(rm.Get());
215 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
216 const auto shifted = Alu32::Shift(m, shift_res.type, shift_res.value,
217 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
218 const auto result = Alu32::AddWithCarry(n, shifted,
false);
219 const auto op_res =
OpResult{result.value, result.carry_out, result.overflow};
220 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
221 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
222 PostExecAdvancePcAndIt::Call(ictx, iflags);
223 return Ok(kNoInstrExecFlags);
233 template <
typename TDest,
typename TArg0,
typename TArg1>
235 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm,
237 auto n = ictx.cpua.ReadRegister(rn.Get());
238 auto m = ictx.cpua.ReadRegister(rm.Get());
239 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
240 const auto shifted = Alu32::Shift(m, shift_res.type, shift_res.value,
241 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
243 Alu32::AddWithCarry(n, shifted, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
244 const auto op_res =
OpResult{result.value, result.carry_out, result.overflow};
245 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
246 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
247 PostExecAdvancePcAndIt::Call(ictx, iflags);
248 return Ok(kNoInstrExecFlags);
252template <
typename TOp,
typename TInstrContext>
class TernaryInstrWithShift {
254 using It =
typename TInstrContext::It;
255 using Pc =
typename TInstrContext::Pc;
257 template <
typename TDest,
typename TArg0,
typename TArg1>
259 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm,
262 if (!condition_passed) {
263 PostExecAdvancePcAndIt::Call(ictx, iflags);
276 TernaryInstrWithShift() =
delete;
281 ~TernaryInstrWithShift() =
delete;
287 TernaryInstrWithShift(
const TernaryInstrWithShift &r_src) =
delete;
293 TernaryInstrWithShift &operator=(
const TernaryInstrWithShift &r_src) =
delete;
299 TernaryInstrWithShift(TernaryInstrWithShift &&r_src) =
delete;
305 TernaryInstrWithShift &operator=(TernaryInstrWithShift &&r_src) =
delete;
#define TRY_ASSIGN(NAME, OUT_TYPE, CALL)
Try to assign a value to a variable and return an error if the assignment fails.
Definition result.h:123