libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
reset_logic.h
Go to the documentation of this file.
1
5#pragma once
6
7#include "libmicroemu/internal/logic/reg_access.h"
8#include "libmicroemu/internal/logic/spec_reg_access.h"
9#include "libmicroemu/internal/processor/step_flags.h"
11#include "libmicroemu/internal/trace/intstr_to_mnemonic.h"
12#include "libmicroemu/logger.h"
13#include "libmicroemu/machine.h"
14#include "libmicroemu/register_details.h"
16#include "libmicroemu/types.h"
17#include <assert.h>
18#include <cstddef>
19#include <cstdint>
20
21namespace libmicroemu::internal {
22
30template <typename TCpuAccessor, typename TBus, typename TProcessorOps,
31 typename TLogger = NullLogger>
32class ResetLogic {
33public:
34 using Exc = typename TProcessorOps::Exc;
35 using Pc = typename TProcessorOps::Pc;
36
43 static Result<void> TakeReset(TCpuAccessor &cpua, TBus &bus) {
44 // see Armv7-M Architecture Reference Manual Issue E.e p.531
45 LOG_INFO(TLogger, "Resetting processor");
46
47 auto sys_ctrl = cpua.template ReadSpecialRegister<SpecialRegisterId::kSysCtrl>();
48
49 // CurrentMode = Mode_Thread;
50 sys_ctrl &= ~static_cast<u32>(SysCtrlRegister::kExecModeMsk);
51 sys_ctrl |= static_cast<u32>(SysCtrlRegister::kExecModeThread);
52
53 // PRIMASK<0> = '0'; /* priority mask cleared at reset */
54 // FAULTMASK<0> = '0'; /* fault mask cleared at reset */
55 // BASEPRI<7:0> = Zeros(8); /* base priority disabled at reset */
56
57 // if HaveFPExt() then /* initialize the Floating Point Extn */
58 if (false) {
59 // CONTROL<2:0> = '000'; /* FP inactive, stack is Main, thread is privileged */
60 // CPACR.cp10 = '00';
61 // CPACR.cp11 = '00';
62 // FPDSCR.AHP = '0';
63 // FPDSCR.DN = '0';
64 // FPDSCR.FZ = '0';
65 // FPDSCR.RMode = '00';
66 // FPCCR.ASPEN = '1';
67 // FPCCR.LSPEN = '1';
68 // FPCCR.LSPACT = '0';
69 // FPCAR = bits(32) UNKNOWN;
70 // FPFSR = bits(32) UNKNOWN;
71 // for i = 0 to 31
72 // S[i] = bits(32) UNKNOWN;
73 } else {
74 // CONTROL<1:0> = '00'; /* current stack is Main, thread is privileged */
75 sys_ctrl &= ~static_cast<u32>(SysCtrlRegister::kControlSpSelMsk);
76 sys_ctrl &= ~static_cast<u32>(SysCtrlRegister::kControlNPrivMsk);
77 }
78
79 cpua.template WriteSpecialRegister<SpecialRegisterId::kSysCtrl>(sys_ctrl);
80
81 // for i = 0 to 511 /* all exceptions Inactive */
82 // ExceptionActive[i] = '0';
83 Exc::InitDefaultExceptionStates(cpua);
84
85 // ResetSCSRegs(); /* catch-all function for System Control Space reset */
86 // ClearExclusiveLocal(ProcessorID()); /* Synchronization (LDREX* / STREX*) monitor support */
87 // ClearEventRegister(); /* see WFE instruction for more details */
88
89 // All registers are UNKNOWN
90 // for i = 0 to 12
91 // R[i] = bits(32) UNKNOWN;
92
93 // bits(32) vectortable = VTOR<31:7>:'0000000';
94 const auto vtor = cpua.template ReadSpecialRegister<SpecialRegisterId::kVtor>();
95 me_adr_t vectortable = vtor << 7 | 0x0U;
96
97 // SP_main = MemA_with_priv[vectortable, 4, AccType_VECTABLE] AND 0xFFFFFFFC<31:0>;
98 TRY_ASSIGN(sp_main, void,
99 bus.template ReadOrRaise<u32>(cpua, vectortable,
100 BusExceptionType::kRaisePreciseDataBusError));
101 cpua.template WriteSpecialRegister<SpecialRegisterId::kSpMain>(sp_main);
102
103 // SP_process = ((bits(30) UNKNOWN):'00');
104 auto sp_process = cpua.template ReadSpecialRegister<SpecialRegisterId::kSpProcess>();
105 sp_process &= ~0x3U; // clear the two least significant bits
106 cpua.template WriteSpecialRegister<SpecialRegisterId::kSpProcess>(sp_process);
107
108 // LR = 0xFFFFFFFF<31:0>; /* preset to an illegal exception return value */
109 cpua.template WriteRegister<RegisterId::kLr>(0xFFFFFFFFU);
110
111 // tmp = MemA_with_priv[vectortable+4, 4, AccType_VECTABLE];
112 TRY_ASSIGN(tmp, void,
113 bus.template ReadOrRaise<u32>(cpua, vectortable + 0x4U,
114 BusExceptionType::kRaisePreciseDataBusError));
115
116 // tbit = tmp<0>;
117 auto tbit = tmp & 0x1U;
118
119 // APSR = bits(32) UNKNOWN; /* flags UNPREDICTABLE from reset */
120
121 // IPSR<8:0> = Zeros(9); /* Exception Number cleared */
122 auto ipsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kIpsr>();
123 ipsr &= ~static_cast<u32>(IpsrRegister::kExceptionNumberMsk);
124 cpua.template WriteSpecialRegister<SpecialRegisterId::kIpsr>(ipsr);
125
126 // EPSR.T = tbit; /* T bit set from vector */
127 // EPSR.IT<7:0> = Zeros(8); /* IT/ICI bits cleared */
128 auto epsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kEpsr>();
129 epsr &= ~static_cast<u32>(EpsrRegister::kItMsk) & // clear it bits
130 ~static_cast<u32>(EpsrRegister::kTMsk); // clear t bit
131 epsr |= tbit << EpsrRegister::kTPos;
132 cpua.template WriteSpecialRegister<SpecialRegisterId::kEpsr>(epsr);
133
134 // BranchTo(tmp AND 0xFFFFFFFE<31:0>); /* address of reset service routine */
135 auto entry_point = tmp & 0xFFFFFFFEU;
136 Pc::BranchTo(cpua, entry_point);
137 LOG_DEBUG(TLogger, "Set entry Point to 0x%08X / tbit:%i", entry_point, tbit);
138
139 // CSR.STKALIGN = '1'; <-- added as default
140 /* stack alignment is 8-byte aligned per default*/
141 auto ccr = cpua.template ReadSpecialRegister<SpecialRegisterId::kCcr>();
142 ccr |= static_cast<u32>(CcrRegister::kStkAlignMsk);
143 cpua.template WriteSpecialRegister<SpecialRegisterId::kCcr>(ccr);
144 LOG_TRACE(TLogger, "CSR: 0x%08X", ccr);
145
146#if IS_LOGLEVEL_TRACE_ENABLED == true // LOG TRACE apsr, ipsr, epsr, xpsr
147 {
148 auto apsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
149 auto ipsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kIpsr>();
150 auto epsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kEpsr>();
151 auto xpsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kXpsr>();
152 LOG_DEBUG(TLogger, "APSR: 0x%08X, IPSR: 0x%08X, EPSR: 0x%08X, XPSR: 0x%08X", apsr, ipsr, epsr,
153 xpsr);
154 }
155#endif
156 return Ok();
157 }
158
159private:
160 ResetLogic() = delete;
161 ~ResetLogic() = delete;
162 ResetLogic(ResetLogic &r_src) = delete;
163 ResetLogic &operator=(const ResetLogic &r_src) = delete;
164 ResetLogic(ResetLogic &&r_src) = delete;
165 ResetLogic &operator=(ResetLogic &&r_src) = delete;
166};
167
168} // namespace libmicroemu::internal
Reset logic for the processor.
Definition reset_logic.h:32
static Result< void > TakeReset(TCpuAccessor &cpua, TBus &bus)
Reset the processor.
Definition reset_logic.h:43
Contains the Machine class which is the main emulation machine for handling microcontroller emulation...
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
This file contains the declaration of the SpecialRegisterId enumeration and related functions.
Definition result.h:15