libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
binary_instr_with_imm_carry.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 Orr1ImmCarryOp {
19public:
20 template <typename TDest, typename TArg0>
21 static Result<InstrExecFlagsSet> Call(const TInstrContext &ictx, const InstrFlagsSet &iflags,
22 const TDest &rd, const TArg0 &rn,
23 const ThumbImmediateResult &imm_carry) {
24 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
25 const auto n = ictx.cpua.ReadRegister(rn.Get());
26
27 const auto result = Alu32::OR(n, imm_carry.out);
28 const auto op_res =
29 OpResult{result, imm_carry.carry_out, (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
30
31 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
32 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
33 PostExecAdvancePcAndIt::Call(ictx, iflags);
34 return Ok(kNoInstrExecFlags);
35 }
36};
37
43template <typename TInstrContext> class Eor1ImmCarryOp {
44public:
45 template <typename TDest, typename TArg0>
46 static Result<InstrExecFlagsSet> Call(const TInstrContext &ictx, const InstrFlagsSet &iflags,
47 const TDest &rd, const TArg0 &rn,
48 const ThumbImmediateResult &imm_carry) {
49 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
50 const auto n = ictx.cpua.ReadRegister(rn.Get());
51 const auto result = Alu32::EOR(n, imm_carry.out);
52 const auto op_res =
53 OpResult{result, imm_carry.carry_out, (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
54 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
55 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
56 PostExecAdvancePcAndIt::Call(ictx, iflags);
57 return Ok(kNoInstrExecFlags);
58 }
59};
60
66template <typename TInstrContext> class And1ImmCarryOp {
67public:
68 template <typename TDest, typename TArg0>
69 static Result<InstrExecFlagsSet> Call(const TInstrContext &ictx, const InstrFlagsSet &iflags,
70 const TDest &rd, const TArg0 &rn,
71 const ThumbImmediateResult &imm_carry) {
72 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
73 const auto n = ictx.cpua.ReadRegister(rn.Get());
74 const auto result = Alu32::AND(n, imm_carry.out);
75 const auto op_res =
76 OpResult{result, imm_carry.carry_out, (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
77 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
78 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
79 PostExecAdvancePcAndIt::Call(ictx, iflags);
80 return Ok(kNoInstrExecFlags);
81 }
82};
83
89template <typename TInstrContext> class Bic1ImmCarryOp {
90public:
91 template <typename TDest, typename TArg0>
92 static Result<InstrExecFlagsSet> Call(const TInstrContext &ictx, const InstrFlagsSet &iflags,
93 const TDest &rd, const TArg0 &rn,
94 const ThumbImmediateResult &imm_carry) {
95 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
96 const auto n = ictx.cpua.ReadRegister(rn.Get());
97 const auto result = Alu32::AND(n, ~imm_carry.out);
98 const auto op_res =
99 OpResult{result, imm_carry.carry_out, (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
100 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
101 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
102 PostExecAdvancePcAndIt::Call(ictx, iflags);
103 return Ok(kNoInstrExecFlags);
104 }
105};
106
107template <typename TOp, typename TInstrContext> class BinaryInstrWithImmCarry {
108public:
109 using It = typename TInstrContext::It;
110 using Pc = typename TInstrContext::Pc;
111
112 template <typename TDest, typename TArg0>
113 static Result<InstrExecResult> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
114 const TDest &rd, const TArg0 &rn,
115 const ThumbImmediateResult &imm_carry) {
116 TRY_ASSIGN(condition_passed, InstrExecResult, It::ConditionPassed(ictx.cpua));
117 if (!condition_passed) {
118 PostExecAdvancePcAndIt::Call(ictx, iflags);
119 return Ok(InstrExecResult{kNoInstrExecFlags});
120 }
121
122 TRY_ASSIGN(eflags, InstrExecResult, TOp::Call(ictx, iflags, rd, rn, imm_carry));
123 return Ok(InstrExecResult{eflags});
124 }
125
126private:
130 BinaryInstrWithImmCarry() = delete;
131
135 ~BinaryInstrWithImmCarry() = delete;
136
141 BinaryInstrWithImmCarry(const BinaryInstrWithImmCarry &r_src) = delete;
142
147 BinaryInstrWithImmCarry &operator=(const BinaryInstrWithImmCarry &r_src) = delete;
148
153 BinaryInstrWithImmCarry(BinaryInstrWithImmCarry &&r_src) = delete;
154
159 BinaryInstrWithImmCarry &operator=(BinaryInstrWithImmCarry &&r_src) = delete;
160};
161
162} // namespace libmicroemu::internal
And.
Definition binary_instr_with_imm_carry.h:66
Bit clear.
Definition binary_instr_with_imm_carry.h:89
Eor.
Definition binary_instr_with_imm_carry.h:43
Orr.
Definition binary_instr_with_imm_carry.h:18
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 thumb_immediate_result.h:6
Definition instr_exec_results.h:23
Definition post_exec.h:12
Definition result.h:15