libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
unary_instr.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 Clz1Op {
19public:
20 template <typename TDest, typename TArg1>
21 static Result<InstrExecFlagsSet> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
22 const TDest &rd, const TArg1 &rm) {
23 using It = typename TInstrContext::It;
24 using Pc = typename TInstrContext::Pc;
25
26 const auto m = ictx.cpua.ReadRegister(rm.Get());
27 const u32 result = Bm32::CountLeadingZeros(m);
28 const auto op_res = OpResult{result, false, false};
29
30 if (rd.Get() == RegisterId::kPc) {
31 Pc::ALUWritePC(ictx.cpua, op_res.value);
32 It::ITAdvance(ictx.cpua);
33 return Ok(kNoInstrExecFlags);
34 } else {
35 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
36 }
37
38 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
39 PostExecAdvancePcAndIt::Call(ictx, iflags);
40 return Ok(kNoInstrExecFlags);
41 }
42};
43
49template <typename TInstrContext> class Mov1Op {
50public:
51 template <typename TDest, typename TArg1>
52 static Result<InstrExecFlagsSet> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
53 const TDest &rd, const TArg1 &rm) {
54 using It = typename TInstrContext::It;
55 using Pc = typename TInstrContext::Pc;
56
57 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
58 const auto m = ictx.cpua.ReadRegister(rm.Get());
59 const auto op_res = OpResult{m, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk,
60 (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
61
62 if (rd.Get() == RegisterId::kPc) {
63 Pc::ALUWritePC(ictx.cpua, op_res.value);
64 It::ITAdvance(ictx.cpua);
65 return Ok(kNoInstrExecFlags);
66 } else {
67 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
68 }
69 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
70 PostExecAdvancePcAndIt::Call(ictx, iflags);
71 return Ok(kNoInstrExecFlags);
72 }
73};
74
80template <typename TInstrContext> class Rrx1Op {
81public:
82 template <typename TDest, typename TArg1>
83 static Result<InstrExecFlagsSet> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
84 const TDest &rd, const TArg1 &rm) {
85 using It = typename TInstrContext::It;
86 using Pc = typename TInstrContext::Pc;
87
88 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
89 const auto m = ictx.cpua.ReadRegister(rm.Get());
90 auto r_rrx = Alu32::Shift_C(m, SRType::SRType_RRX, 1U,
91 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
92
93 const auto op_res = OpResult{r_rrx.result, r_rrx.carry_out,
94 (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
95
96 if (rd.Get() == RegisterId::kPc) {
97 Pc::ALUWritePC(ictx.cpua, op_res.value);
98 It::ITAdvance(ictx.cpua);
99 return Ok(kNoInstrExecFlags);
100 } else {
101 PostExecWriteRegPcExcluded::Call(ictx, rd, op_res.value);
102 }
103 PostExecOptionalSetFlags::Call(ictx, iflags, op_res);
104 PostExecAdvancePcAndIt::Call(ictx, iflags);
105 return Ok(kNoInstrExecFlags);
106 }
107};
108
109template <typename TOp, typename TInstrContext> class UnaryInstr {
110public:
111 using It = typename TInstrContext::It;
112 using Pc = typename TInstrContext::Pc;
113
114 template <typename TDest, typename TArg1>
115 static Result<InstrExecResult> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
116 const TDest &rd, const TArg1 &rm) {
117 TRY_ASSIGN(condition_passed, InstrExecResult, It::ConditionPassed(ictx.cpua));
118 if (!condition_passed) {
119 PostExecAdvancePcAndIt::Call(ictx, iflags);
120 return Ok(InstrExecResult{kNoInstrExecFlags});
121 }
122
123 TRY_ASSIGN(eflags, InstrExecResult, TOp::Call(ictx, iflags, rd, rm));
124 return Ok(InstrExecResult{eflags});
125 }
126
127private:
131 UnaryInstr() = delete;
132
136 ~UnaryInstr() = delete;
137
142 UnaryInstr(const UnaryInstr &r_src) = delete;
143
148 UnaryInstr &operator=(const UnaryInstr &r_src) = delete;
149
154 UnaryInstr(UnaryInstr &&r_src) = delete;
155
160 UnaryInstr &operator=(UnaryInstr &&r_src) = delete;
161};
162
163} // namespace libmicroemu::internal
Clz.
Definition unary_instr.h:18
Mov.
Definition unary_instr.h:49
Rrx.
Definition unary_instr.h:80
The libmicroemu::internal namespace contains all classes and functions of libmicroemu which are priva...
Definition bkpt_flags.h:6
@ kPc
Program-counter register.
Definition register_id.h:34
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