libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
binary_instr_with_imm.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 {
17template <typename TInstrContext> class Add1ImmOp {
18public:
19 template <typename TDest, typename TArg0>
20 static Result<InstrExecFlagsSet> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
21 const TDest &rd, const TArg0 &rn, const u32 &imm) {
22 const auto n = ictx.cpua.ReadRegister(rn.Get());
23 const auto result = Alu32::AddWithCarry(n, imm, false);
24 const auto op_res = OpResult{result.value, result.carry_out, result.overflow};
25 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
26 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
27 PostExecAdvancePcAndIt::Call(ictx, iflags);
28 return Ok(kNoInstrExecFlags);
29 }
30};
31
37template <typename TInstrContext> class Adc1ImmOp {
38public:
39 template <typename TDest, typename TArg0>
40 static Result<InstrExecFlagsSet> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
41 const TDest &rd, const TArg0 &rn, const u32 &imm) {
42 const auto n = ictx.cpua.ReadRegister(rn.Get());
43 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
44 const auto result =
45 Alu32::AddWithCarry(n, imm, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
46 const auto op_res = OpResult{result.value, result.carry_out, result.overflow};
47
48 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
49 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
50 PostExecAdvancePcAndIt::Call(ictx, iflags);
51 return Ok(kNoInstrExecFlags);
52 }
53};
54
60template <typename TInstrContext> class Sub1ImmOp {
61public:
62 template <typename TDest, typename TArg0>
63 static Result<InstrExecFlagsSet> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
64 const TDest &rd, const TArg0 &rn, const u32 &imm) {
65 const auto n = ictx.cpua.ReadRegister(rn.Get());
66 const auto result = Alu32::AddWithCarry(n, ~imm, true);
67 const auto op_res = OpResult{result.value, result.carry_out, result.overflow};
68
69 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
70 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
71 PostExecAdvancePcAndIt::Call(ictx, iflags);
72 return Ok(kNoInstrExecFlags);
73 }
74};
75
81template <typename TInstrContext> class Sbc1ImmOp {
82public:
83 template <typename TDest, typename TArg0>
84 static Result<InstrExecFlagsSet> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
85 const TDest &rd, const TArg0 &rn, const u32 &imm) {
86 const auto n = ictx.cpua.ReadRegister(rn.Get());
87 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
88 const auto result =
89 Alu32::AddWithCarry(n, ~imm, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
90 const auto op_res = OpResult{result.value, result.carry_out, result.overflow};
91
92 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
93 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
94 PostExecAdvancePcAndIt::Call(ictx, iflags);
95 return Ok(kNoInstrExecFlags);
96 }
97};
98
104template <typename TInstrContext> class Rsb1ImmOp {
105public:
106 template <typename TDest, typename TArg0>
107 static Result<InstrExecFlagsSet> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
108 const TDest &rd, const TArg0 &rn, const u32 &imm) {
109 const auto n = ictx.cpua.ReadRegister(rn.Get());
110 const auto result = Alu32::AddWithCarry(~n, imm, true);
111 const auto op_res = OpResult{result.value, result.carry_out, result.overflow};
112 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
113
114 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
115 PostExecAdvancePcAndIt::Call(ictx, iflags);
116 return Ok(kNoInstrExecFlags);
117 }
118};
119
120template <typename TOp, typename TInstrContext> class BinaryInstrWithImm {
121public:
122 using It = typename TInstrContext::It;
123 using Pc = typename TInstrContext::Pc;
124
125 template <typename TDest, typename TArg0>
126 static Result<InstrExecResult> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
127 const TDest &rd, const TArg0 &rn, const u32 &imm) {
128
129 TRY_ASSIGN(condition_passed, InstrExecResult, It::ConditionPassed(ictx.cpua));
130 if (!condition_passed) {
131 PostExecAdvancePcAndIt::Call(ictx, iflags);
132 return Ok(InstrExecResult{kNoInstrExecFlags});
133 }
134
135 TRY_ASSIGN(eflags, InstrExecResult, TOp::Call(ictx, iflags, rd, rn, imm));
136 return Ok(InstrExecResult{eflags});
137 }
138
139private:
143 BinaryInstrWithImm() = delete;
144
148 ~BinaryInstrWithImm() = delete;
149
154 BinaryInstrWithImm(const BinaryInstrWithImm &r_src) = delete;
155
160 BinaryInstrWithImm &operator=(const BinaryInstrWithImm &r_src) = delete;
161
166 BinaryInstrWithImm(BinaryInstrWithImm &&r_src) = delete;
167
172 BinaryInstrWithImm &operator=(BinaryInstrWithImm &&r_src) = delete;
173};
174
175} // namespace libmicroemu::internal
Adc.
Definition binary_instr_with_imm.h:37
Add.
Definition binary_instr_with_imm.h:17
Reverse Subtract.
Definition binary_instr_with_imm.h:104
Subtract with carry.
Definition binary_instr_with_imm.h:81
Subtract.
Definition binary_instr_with_imm.h:60
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 instr_exec_results.h:23
Definition post_exec.h:12
Definition result.h:15