19template <
typename TInstrContext>
class Lsr2Op {
21 template <
typename TDest,
typename TArg0,
typename TArg1>
23 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm) {
24 const auto n = ictx.cpua.ReadRegister(rn.Get());
25 const auto m = ictx.cpua.ReadRegister(rm.Get());
26 const auto shift_n = m & 0xFFU;
28 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
29 auto r_shift_c = Alu32::Shift_C(n, SRType::SRType_LSR, shift_n,
30 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
32 const auto op_res =
OpResult{r_shift_c.result, r_shift_c.carry_out,
33 (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);
39 return Ok(kNoInstrExecFlags);
48template <
typename TInstrContext>
class Asr2Op {
50 template <
typename TDest,
typename TArg0,
typename TArg1>
52 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm) {
53 const auto n = ictx.cpua.ReadRegister(rn.Get());
54 const auto m = ictx.cpua.ReadRegister(rm.Get());
55 const auto shift_n = m & 0xFFU;
57 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
58 auto r_shift_c = Alu32::Shift_C(n, SRType::SRType_ASR, shift_n,
59 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
61 const auto op_res =
OpResult{r_shift_c.result, r_shift_c.carry_out,
62 (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
64 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
65 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
66 PostExecAdvancePcAndIt::Call(ictx, iflags);
68 return Ok(kNoInstrExecFlags);
77template <
typename TInstrContext>
class Lsl2Op {
79 template <
typename TDest,
typename TArg0,
typename TArg1>
81 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm) {
83 const auto n = ictx.cpua.ReadRegister(rn.Get());
84 const auto m = ictx.cpua.ReadRegister(rm.Get());
85 const auto shift_n = m & 0xFFU;
87 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
88 auto r_shift_c = Alu32::Shift_C(n, SRType::SRType_LSL, shift_n,
89 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
91 const auto op_res =
OpResult{r_shift_c.result, r_shift_c.carry_out,
92 (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
94 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
95 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
96 PostExecAdvancePcAndIt::Call(ictx, iflags);
97 return Ok(kNoInstrExecFlags);
106template <
typename TInstrContext>
class Mul2Op {
108 template <
typename TDest,
typename TArg0,
typename TArg1>
110 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm) {
111 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
112 const auto n = ictx.cpua.ReadRegister(rn.Get());
113 const auto m = ictx.cpua.ReadRegister(rm.Get());
114 const auto result =
static_cast<u32
>(
static_cast<i32
>(n) *
static_cast<i32
>(m));
116 const auto op_res =
OpResult{result, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk,
117 (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);
131template <
typename TInstrContext>
class UDiv2Op {
133 using ExcTrig =
typename TInstrContext::ExcTrig;
134 static inline bool IntegerZeroDivideTrappingEnabled(
const TInstrContext &ictx) {
135 const auto ccr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kCcr>();
136 return (ccr & CcrRegister::kDivByZeroTrapEnableMsk) != 0U;
139 static inline void GenerateIntegerZeroDivide(
const TInstrContext &ictx) {
141 auto cfsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kCfsr>();
142 cfsr |= CfsrUsageFault::kDivByZeroMsk;
143 ictx.cpua.template WriteSpecialRegister<SpecialRegisterId::kCfsr>(cfsr);
146 template <
typename TDest,
typename TArg0,
typename TArg1>
148 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm) {
150 const auto n = ictx.cpua.ReadRegister(rn.Get());
151 const auto m = ictx.cpua.ReadRegister(rm.Get());
152 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
156 if (IntegerZeroDivideTrappingEnabled(ictx)) {
157 GenerateIntegerZeroDivide(ictx);
165 const auto op_res =
OpResult{result, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk,
166 (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
167 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
168 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
169 PostExecAdvancePcAndIt::Call(ictx, iflags);
170 return Ok(kNoInstrExecFlags);
179template <
typename TInstrContext>
class SDiv2Op {
181 using ExcTrig =
typename TInstrContext::ExcTrig;
183 static inline bool IntegerZeroDivideTrappingEnabled(
const TInstrContext &ictx) {
184 const auto ccr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kCcr>();
185 return (ccr & CcrRegister::kDivByZeroTrapEnableMsk) != 0U;
188 static inline void GenerateIntegerZeroDivide(
const TInstrContext &ictx) {
190 auto cfsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kCfsr>();
191 cfsr |= CfsrUsageFault::kDivByZeroMsk;
192 ictx.cpua.template WriteSpecialRegister<SpecialRegisterId::kCfsr>(cfsr);
195 template <
typename TDest,
typename TArg0,
typename TArg1>
197 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm) {
199 const auto n = ictx.cpua.ReadRegister(rn.Get());
200 const auto m = ictx.cpua.ReadRegister(rm.Get());
201 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
204 if (IntegerZeroDivideTrappingEnabled(ictx)) {
205 GenerateIntegerZeroDivide(ictx);
210 result =
static_cast<u32
>(
static_cast<i32
>(n) /
static_cast<i32
>(m));
213 const auto op_res =
OpResult{result, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk,
214 (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
215 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
217 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
218 PostExecAdvancePcAndIt::Call(ictx, iflags);
219 return Ok(kNoInstrExecFlags);
222template <
typename TOp,
typename TInstrContext>
class BinaryInstr {
224 using It =
typename TInstrContext::It;
225 using Pc =
typename TInstrContext::Pc;
227 template <
typename TDest,
typename TArg0,
typename TArg1>
229 const TDest &rd,
const TArg0 &rn,
const TArg1 &rm) {
231 if (!condition_passed) {
232 PostExecAdvancePcAndIt::Call(ictx, iflags);
244 BinaryInstr() =
delete;
249 ~BinaryInstr() =
delete;
255 BinaryInstr(
const BinaryInstr &r_src) =
delete;
261 BinaryInstr &operator=(
const BinaryInstr &r_src) =
delete;
267 BinaryInstr(BinaryInstr &&r_src) =
delete;
273 BinaryInstr &operator=(BinaryInstr &&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