libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
pc_ops.h
1#pragma once
2
5#include "libmicroemu/types.h"
6#include <cstddef>
7#include <cstdint>
8
9namespace libmicroemu::internal {
10
11template <typename TCpuAccessor, typename TBus, typename TExceptionReturn,
12 typename TLogger = NullLogger>
13class PcOps {
14public:
15 using ExcRet = TExceptionReturn;
16
17 static inline void BranchTo(TCpuAccessor &cpua, const me_adr_t &pc) {
18 auto &registers = cpua.GetRegisters();
19 registers[static_cast<u8>(RegisterId::kPc)] = pc;
20 }
21
22 static inline void BranchWritePC(TCpuAccessor &cpua, const me_adr_t &address) {
23 // see Armv7-M Architecture Reference Manual Issue E.e p.30
24 BranchTo(cpua, address & (~0x1U));
25 }
26
27 static inline Result<void> BXWritePC(TCpuAccessor &cpua, TBus &bus, const me_adr_t &address) {
28 // see Armv7-M Architecture Reference Manual Issue E.e p.31
29 const auto is_handler_mode = Predicates::IsHandlerMode(cpua);
30
31 // if CurrentMode == Mode_Handler && address<31:28> == ‘1111’ then
32 if (is_handler_mode && ((address & 0xF0000000U) == 0xF0000000U)) {
33 LOG_TRACE(TLogger, "BXWritePC (Exception Return): address=0x%08X, is_handler_mode=%d",
34 address, is_handler_mode);
35 // ExceptionReturn(address<27:0>);
36 return ExcRet::Return(cpua, bus, address & 0x0FFFFFFFU);
37 } else {
38 auto epsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kEpsr>();
39
40 if ((address & 0x1U) == 0U) {
41 LOG_ERROR(TLogger, "BXWritePC: Set wrong execution state");
42 }
43
44 // EPSR.T = address<0>;
45 // if EPSR.T == 0, a UsageFault(‘Invalid State’) is taken on the next instruction
46 epsr &= ~EpsrRegister::kTMsk;
47 epsr |= (address & 0x1U) << EpsrRegister::kTPos;
48 cpua.template WriteSpecialRegister<SpecialRegisterId::kEpsr>(epsr);
49 BranchTo(cpua, address & (~0x1));
50 return Ok();
51 }
52 // should never reach here
53 }
54
55 static inline void BLXWritePC(TCpuAccessor &cpua, const me_adr_t &address) {
56 // see Armv7-M Architecture Reference Manual Issue E.e p.31
57
58 if (address & 0x1) {
59 LOG_ERROR(TLogger, "BLXWritePC: Set wrong execution state");
60 }
61 // EPSR.T = address<0>;
62 // if EPSR.T == 0, a UsageFault(‘Invalid State’) is taken on the next instruction
63 auto epsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kEpsr>();
64 epsr &= ~EpsrRegister::kTMsk;
65 epsr |= (address & 0x1U) << EpsrRegister::kTPos;
66 cpua.template WriteSpecialRegister<SpecialRegisterId::kEpsr>(epsr);
67 BranchTo(cpua, address & (~0x1U));
68 }
69
70 static inline Result<void> LoadWritePC(TCpuAccessor &cpua, TBus &bus, const me_adr_t &address) {
71 // see Armv7-M Architecture Reference Manual Issue E.e p.31
72 return BXWritePC(cpua, bus, address);
73 }
74
75 static inline void ALUWritePC(TCpuAccessor &cpua, const me_adr_t &address) {
76 // see Armv7-M Architecture Reference Manual Issue E.e p.31
77 BranchWritePC(cpua, address);
78 }
79
84 static inline void AdvanceInstr(TCpuAccessor &cpua, bool is_32bit) {
85 // The pc points to the current instruction +4. Therefore decrement 2
86 // in case we have a 16 bit instruction
87
88 me_adr_t pc = static_cast<me_adr_t>(cpua.template ReadRegister<RegisterId::kPc>());
89 pc += is_32bit ? 0U : -2U;
90 BranchTo(cpua, pc);
91 }
92
93private:
97 PcOps() = delete;
98
102 ~PcOps() = delete;
103
108 PcOps(PcOps &r_src) = delete;
109
114 PcOps &operator=(const PcOps &r_src) = delete;
115
120 PcOps(PcOps &&r_src) = delete;
121
126 PcOps &operator=(PcOps &&r_src) = delete;
127};
128
129} // namespace libmicroemu::internal
Definition pc_ops.h:13
static void AdvanceInstr(TCpuAccessor &cpua, bool is_32bit)
Advances the program counter to the next instruction.
Definition pc_ops.h:84
static bool IsHandlerMode(const TCpuAccessor &cpua)
Check if the cpu is in handler mode.
Definition predicates.h:38
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
This file contains the declaration of the Predicates class.
Contains the Result class which is used to return the result of a function.
Definition register_details.h:207
Definition result.h:15