libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
binary_instr_with_shift.h
1#pragma once
2#include "libmicroemu/internal/decoder/decoder.h"
3#include "libmicroemu/internal/executor/instr/post_exec.h"
4#include "libmicroemu/internal/executor/instr_context.h"
5#include "libmicroemu/internal/executor/instr_exec_results.h"
7#include "libmicroemu/internal/utils/rarg.h"
8#include "libmicroemu/register_details.h"
9#include "libmicroemu/types.h"
10
11namespace libmicroemu::internal {
12
18template <typename TInstrContext> class Asr1ShiftOp {
19public:
20 template <typename TDest, typename TArg0>
21 static Result<InstrExecFlagsSet> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
22 const TDest &rd, const TArg0 &rm,
23 const ImmShiftResults &shift_res) {
24 const auto m = ictx.cpua.ReadRegister(rm.Get());
25 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
26 auto r_shift_c = Alu32::Shift_C(m, SRType::SRType_ASR, shift_res.value,
27 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
28
29 const auto op_res = OpResult{r_shift_c.result, r_shift_c.carry_out,
30 (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
31
32 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
33 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
34 PostExecAdvancePcAndIt::Call(ictx, iflags);
35 return Ok(kNoInstrExecFlags);
36 }
37};
38
44template <typename TInstrContext> class Lsl1ShiftOp {
45public:
46 template <typename TDest, typename TArg0>
47 static Result<InstrExecFlagsSet> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
48 const TDest &rd, const TArg0 &rm,
49 const ImmShiftResults &shift_res) {
50 const auto m = ictx.cpua.ReadRegister(rm.Get());
51 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
52 auto r_shift_c = Alu32::Shift_C(m, SRType::SRType_LSL, shift_res.value,
53 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
54
55 const auto op_res = OpResult{r_shift_c.result, r_shift_c.carry_out,
56 (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
57
58 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
59 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
60 PostExecAdvancePcAndIt::Call(ictx, iflags);
61 return Ok(kNoInstrExecFlags);
62 }
63};
64
70template <typename TInstrContext> class Lsr1ShiftOp {
71public:
72 template <typename TDest, typename TArg0>
73 static Result<InstrExecFlagsSet> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
74 const TDest &rd, const TArg0 &rm,
75 const ImmShiftResults &shift_res) {
76 const auto m = ictx.cpua.ReadRegister(rm.Get());
77 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
78 auto r_shift_c = Alu32::Shift_C(m, SRType::SRType_LSR, shift_res.value,
79 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
80
81 const auto op_res = OpResult{r_shift_c.result, r_shift_c.carry_out,
82 (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
83
84 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
85 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
86 PostExecAdvancePcAndIt::Call(ictx, iflags);
87 return Ok(kNoInstrExecFlags);
88 }
89};
90
96template <typename TInstrContext> class Mvn1ShiftOp {
97public:
98 template <typename TDest, typename TArg0>
99 static Result<InstrExecFlagsSet> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
100 const TDest &rd, const TArg0 &rm,
101 const ImmShiftResults &shift_res) {
102 const auto m = ictx.cpua.ReadRegister(rm.Get());
103 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
104 auto r_shift_c = Alu32::Shift_C(m, shift_res.type, shift_res.value,
105 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
106
107 const auto op_res = OpResult{~r_shift_c.result, r_shift_c.carry_out,
108 (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
109
110 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
111 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
112 PostExecAdvancePcAndIt::Call(ictx, iflags);
113 return Ok(kNoInstrExecFlags);
114 }
115};
116
117template <typename TOp, typename TInstrContext> class BinaryInstrWithShift {
118public:
119 using It = typename TInstrContext::It;
120 using Pc = typename TInstrContext::Pc;
121
122 template <typename TDest, typename TArg0>
123 static Result<InstrExecResult> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
124 const TDest &rd, const TArg0 &rm,
125 const ImmShiftResults &shift_res) {
126 TRY_ASSIGN(condition_passed, InstrExecResult, It::ConditionPassed(ictx.cpua));
127 if (!condition_passed) {
128 PostExecAdvancePcAndIt::Call(ictx, iflags);
129 return Ok(InstrExecResult{kNoInstrExecFlags});
130 }
131
132 TRY_ASSIGN(eflags, InstrExecResult, TOp::Call(ictx, iflags, rd, rm, shift_res));
133 return Ok(InstrExecResult{eflags});
134 }
135
136private:
140 BinaryInstrWithShift() = delete;
141
145 ~BinaryInstrWithShift() = delete;
146
151 BinaryInstrWithShift(const BinaryInstrWithShift &r_src) = delete;
152
157 BinaryInstrWithShift &operator=(const BinaryInstrWithShift &r_src) = delete;
158
163 BinaryInstrWithShift(BinaryInstrWithShift &&r_src) = delete;
164
169 BinaryInstrWithShift &operator=(BinaryInstrWithShift &&r_src) = delete;
170};
171
172} // namespace libmicroemu::internal
Asr.
Definition binary_instr_with_shift.h:18
Lsl.
Definition binary_instr_with_shift.h:44
Lsr.
Definition binary_instr_with_shift.h:70
Mvn.
Definition binary_instr_with_shift.h:96
The libmicroemu::internal namespace contains all classes and functions of libmicroemu which are priva...
Definition bkpt_flags.h:6
Contains the Result class which is used to return the result of a function.
#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
Definition imm_shift_results.h:15
Definition instr_exec_results.h:23
Definition post_exec.h:12
Definition result.h:15