libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
ternary_instr.h
1#pragma once
2#include "libmicroemu/internal/decoder/decoder.h"
3#include "libmicroemu/internal/executor/instr_context.h"
4#include "libmicroemu/internal/executor/instr_exec_results.h"
6#include "libmicroemu/internal/utils/rarg.h"
7#include "libmicroemu/register_details.h"
8#include "libmicroemu/types.h"
9
10namespace libmicroemu::internal {
11
17template <typename TInstrContext> class Mls3Op {
18public:
19 template <typename TDest, typename TArg0, typename TArg1, typename TArg2>
20 static Result<InstrExecFlagsSet> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
21 const TDest &rd, const TArg0 &rn, const TArg1 &rm,
22 const TArg2 &ra) {
23 const auto n = ictx.cpua.ReadRegister(rn.Get());
24 const auto m = ictx.cpua.ReadRegister(rm.Get());
25 const auto a = ictx.cpua.ReadRegister(ra.Get());
26
27 const auto result =
28 static_cast<u32>(static_cast<i32>(a) - static_cast<i32>(n) * static_cast<i32>(m));
29
30 const auto op_result = OpResult{result, false, false};
31
32 PostExecWriteRegPcExcluded::Call(ictx, rd, op_result.value);
33 PostExecOptionalSetFlags::Call(ictx, iflags, op_result);
34 PostExecAdvancePcAndIt::Call(ictx, iflags);
35 return Ok(kNoInstrExecFlags);
36 }
37};
38
44template <typename TInstrContext> class Mla3Op {
45public:
46 template <typename TDest, typename TArg0, typename TArg1, typename TArg2>
47 static Result<InstrExecFlagsSet> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
48 const TDest &rd, const TArg0 &rn, const TArg1 &rm,
49 const TArg2 &ra) {
50 const auto n = ictx.cpua.ReadRegister(rn.Get());
51 const auto m = ictx.cpua.ReadRegister(rm.Get());
52 const auto a = ictx.cpua.ReadRegister(ra.Get());
53
54 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
55
56 const auto result =
57 static_cast<u32>(static_cast<i32>(n) * static_cast<i32>(m) + static_cast<i32>(a));
58
59 const auto op_result = OpResult{result, (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk,
60 (apsr & ApsrRegister::kVMsk) == ApsrRegister::kVMsk};
61
62 PostExecWriteRegPcExcluded::Call(ictx, rd, op_result.value);
63 PostExecOptionalSetFlags::Call(ictx, iflags, op_result);
64 PostExecAdvancePcAndIt::Call(ictx, iflags);
65 return Ok(kNoInstrExecFlags);
66 }
67};
68
69template <typename TOp, typename TInstrContext> class TernaryInstr {
70public:
71 using It = typename TInstrContext::It;
72 using Pc = typename TInstrContext::Pc;
73
74 template <typename TDest, typename TArg0, typename TArg1, typename TArg2>
75 static Result<InstrExecResult> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
76 const TDest &rd, const TArg0 &rn, const TArg1 &rm,
77 const TArg2 &ra) {
78 TRY_ASSIGN(condition_passed, InstrExecResult, It::ConditionPassed(ictx.cpua));
79 if (!condition_passed) {
80 PostExecAdvancePcAndIt::Call(ictx, iflags);
81 return Ok(InstrExecResult{kNoInstrExecFlags});
82 }
83
84 TRY_ASSIGN(eflags, InstrExecResult, TOp::Call(ictx, iflags, rd, rn, rm, ra));
85 return Ok(InstrExecResult{eflags});
86 }
87
88private:
92 TernaryInstr() = delete;
93
97 ~TernaryInstr() = delete;
98
103 TernaryInstr(const TernaryInstr &r_src) = delete;
104
109 TernaryInstr &operator=(const TernaryInstr &r_src) = delete;
110
115 TernaryInstr(TernaryInstr &&r_src) = delete;
116
121 TernaryInstr &operator=(TernaryInstr &&r_src) = delete;
122};
123
124} // namespace libmicroemu::internal
Mla.
Definition ternary_instr.h:44
Mls.
Definition ternary_instr.h:17
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