armstate.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. // Copyright 2015 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include "common/logging/log.h"
  6. #include "common/swap.h"
  7. #include "core/arm/skyeye_common/armstate.h"
  8. #include "core/arm/skyeye_common/vfp/vfp.h"
  9. #include "core/gdbstub/gdbstub.h"
  10. #include "core/memory.h"
  11. ARMul_State::ARMul_State(PrivilegeMode initial_mode) {
  12. Reset();
  13. ChangePrivilegeMode(initial_mode);
  14. }
  15. void ARMul_State::ChangePrivilegeMode(u32 new_mode) {
  16. if (Mode == new_mode)
  17. return;
  18. if (new_mode != USERBANK) {
  19. switch (Mode) {
  20. case SYSTEM32MODE: // Shares registers with user mode
  21. case USER32MODE:
  22. Reg_usr[0] = Reg[13];
  23. Reg_usr[1] = Reg[14];
  24. break;
  25. case IRQ32MODE:
  26. Reg_irq[0] = Reg[13];
  27. Reg_irq[1] = Reg[14];
  28. Spsr[IRQBANK] = Spsr_copy;
  29. break;
  30. case SVC32MODE:
  31. Reg_svc[0] = Reg[13];
  32. Reg_svc[1] = Reg[14];
  33. Spsr[SVCBANK] = Spsr_copy;
  34. break;
  35. case ABORT32MODE:
  36. Reg_abort[0] = Reg[13];
  37. Reg_abort[1] = Reg[14];
  38. Spsr[ABORTBANK] = Spsr_copy;
  39. break;
  40. case UNDEF32MODE:
  41. Reg_undef[0] = Reg[13];
  42. Reg_undef[1] = Reg[14];
  43. Spsr[UNDEFBANK] = Spsr_copy;
  44. break;
  45. case FIQ32MODE:
  46. std::copy(Reg.begin() + 8, Reg.end() - 1, Reg_firq.begin());
  47. Spsr[FIQBANK] = Spsr_copy;
  48. break;
  49. }
  50. switch (new_mode) {
  51. case USER32MODE:
  52. Reg[13] = Reg_usr[0];
  53. Reg[14] = Reg_usr[1];
  54. Bank = USERBANK;
  55. break;
  56. case IRQ32MODE:
  57. Reg[13] = Reg_irq[0];
  58. Reg[14] = Reg_irq[1];
  59. Spsr_copy = Spsr[IRQBANK];
  60. Bank = IRQBANK;
  61. break;
  62. case SVC32MODE:
  63. Reg[13] = Reg_svc[0];
  64. Reg[14] = Reg_svc[1];
  65. Spsr_copy = Spsr[SVCBANK];
  66. Bank = SVCBANK;
  67. break;
  68. case ABORT32MODE:
  69. Reg[13] = Reg_abort[0];
  70. Reg[14] = Reg_abort[1];
  71. Spsr_copy = Spsr[ABORTBANK];
  72. Bank = ABORTBANK;
  73. break;
  74. case UNDEF32MODE:
  75. Reg[13] = Reg_undef[0];
  76. Reg[14] = Reg_undef[1];
  77. Spsr_copy = Spsr[UNDEFBANK];
  78. Bank = UNDEFBANK;
  79. break;
  80. case FIQ32MODE:
  81. std::copy(Reg_firq.begin(), Reg_firq.end(), Reg.begin() + 8);
  82. Spsr_copy = Spsr[FIQBANK];
  83. Bank = FIQBANK;
  84. break;
  85. case SYSTEM32MODE: // Shares registers with user mode.
  86. Reg[13] = Reg_usr[0];
  87. Reg[14] = Reg_usr[1];
  88. Bank = SYSTEMBANK;
  89. break;
  90. }
  91. // Set the mode bits in the APSR
  92. Cpsr = (Cpsr & ~Mode) | new_mode;
  93. Mode = new_mode;
  94. }
  95. }
  96. // Performs a reset
  97. void ARMul_State::Reset() {
  98. VFPInit(this);
  99. // Set stack pointer to the top of the stack
  100. Reg[13] = 0x10000000;
  101. Reg[15] = 0;
  102. Cpsr = INTBITS | SVC32MODE;
  103. Mode = SVC32MODE;
  104. Bank = SVCBANK;
  105. ResetMPCoreCP15Registers();
  106. NresetSig = HIGH;
  107. NfiqSig = HIGH;
  108. NirqSig = HIGH;
  109. NtransSig = (Mode & 3) ? HIGH : LOW;
  110. abortSig = LOW;
  111. NumInstrs = 0;
  112. Emulate = RUN;
  113. }
  114. // Resets certain MPCore CP15 values to their ARM-defined reset values.
  115. void ARMul_State::ResetMPCoreCP15Registers() {
  116. // c0
  117. CP15[CP15_MAIN_ID] = 0x410FB024;
  118. CP15[CP15_TLB_TYPE] = 0x00000800;
  119. CP15[CP15_PROCESSOR_FEATURE_0] = 0x00000111;
  120. CP15[CP15_PROCESSOR_FEATURE_1] = 0x00000001;
  121. CP15[CP15_DEBUG_FEATURE_0] = 0x00000002;
  122. CP15[CP15_MEMORY_MODEL_FEATURE_0] = 0x01100103;
  123. CP15[CP15_MEMORY_MODEL_FEATURE_1] = 0x10020302;
  124. CP15[CP15_MEMORY_MODEL_FEATURE_2] = 0x01222000;
  125. CP15[CP15_MEMORY_MODEL_FEATURE_3] = 0x00000000;
  126. CP15[CP15_ISA_FEATURE_0] = 0x00100011;
  127. CP15[CP15_ISA_FEATURE_1] = 0x12002111;
  128. CP15[CP15_ISA_FEATURE_2] = 0x11221011;
  129. CP15[CP15_ISA_FEATURE_3] = 0x01102131;
  130. CP15[CP15_ISA_FEATURE_4] = 0x00000141;
  131. // c1
  132. CP15[CP15_CONTROL] = 0x00054078;
  133. CP15[CP15_AUXILIARY_CONTROL] = 0x0000000F;
  134. CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = 0x00000000;
  135. // c2
  136. CP15[CP15_TRANSLATION_BASE_TABLE_0] = 0x00000000;
  137. CP15[CP15_TRANSLATION_BASE_TABLE_1] = 0x00000000;
  138. CP15[CP15_TRANSLATION_BASE_CONTROL] = 0x00000000;
  139. // c3
  140. CP15[CP15_DOMAIN_ACCESS_CONTROL] = 0x00000000;
  141. // c7
  142. CP15[CP15_PHYS_ADDRESS] = 0x00000000;
  143. // c9
  144. CP15[CP15_DATA_CACHE_LOCKDOWN] = 0xFFFFFFF0;
  145. // c10
  146. CP15[CP15_TLB_LOCKDOWN] = 0x00000000;
  147. CP15[CP15_PRIMARY_REGION_REMAP] = 0x00098AA4;
  148. CP15[CP15_NORMAL_REGION_REMAP] = 0x44E048E0;
  149. // c13
  150. CP15[CP15_PID] = 0x00000000;
  151. CP15[CP15_CONTEXT_ID] = 0x00000000;
  152. CP15[CP15_THREAD_UPRW] = 0x00000000;
  153. CP15[CP15_THREAD_URO] = 0x00000000;
  154. CP15[CP15_THREAD_PRW] = 0x00000000;
  155. // c15
  156. CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = 0x00000000;
  157. CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = 0x00000000;
  158. CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = 0x00000000;
  159. CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = 0x00000000;
  160. CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000;
  161. }
  162. static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) {
  163. if (GDBStub::IsServerEnabled() && GDBStub::CheckBreakpoint(address, type)) {
  164. LOG_DEBUG(Debug, "Found memory breakpoint @ %08x", address);
  165. GDBStub::Break(true);
  166. }
  167. }
  168. u8 ARMul_State::ReadMemory8(u32 address) const {
  169. CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
  170. return Memory::Read8(address);
  171. }
  172. u16 ARMul_State::ReadMemory16(u32 address) const {
  173. CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
  174. u16 data = Memory::Read16(address);
  175. if (InBigEndianMode())
  176. data = Common::swap16(data);
  177. return data;
  178. }
  179. u32 ARMul_State::ReadMemory32(u32 address) const {
  180. CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
  181. u32 data = Memory::Read32(address);
  182. if (InBigEndianMode())
  183. data = Common::swap32(data);
  184. return data;
  185. }
  186. u64 ARMul_State::ReadMemory64(u32 address) const {
  187. CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
  188. u64 data = Memory::Read64(address);
  189. if (InBigEndianMode())
  190. data = Common::swap64(data);
  191. return data;
  192. }
  193. void ARMul_State::WriteMemory8(u32 address, u8 data) {
  194. CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
  195. Memory::Write8(address, data);
  196. }
  197. void ARMul_State::WriteMemory16(u32 address, u16 data) {
  198. CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
  199. if (InBigEndianMode())
  200. data = Common::swap16(data);
  201. Memory::Write16(address, data);
  202. }
  203. void ARMul_State::WriteMemory32(u32 address, u32 data) {
  204. CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
  205. if (InBigEndianMode())
  206. data = Common::swap32(data);
  207. Memory::Write32(address, data);
  208. }
  209. void ARMul_State::WriteMemory64(u32 address, u64 data) {
  210. CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
  211. if (InBigEndianMode())
  212. data = Common::swap64(data);
  213. Memory::Write64(address, data);
  214. }
  215. // Reads from the CP15 registers. Used with implementation of the MRC instruction.
  216. // Note that since the 3DS does not have the hypervisor extensions, these registers
  217. // are not implemented.
  218. u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const {
  219. // Unprivileged registers
  220. if (crn == 13 && opcode_1 == 0 && crm == 0) {
  221. if (opcode_2 == 2)
  222. return CP15[CP15_THREAD_UPRW];
  223. if (opcode_2 == 3)
  224. return CP15[CP15_THREAD_URO];
  225. }
  226. if (InAPrivilegedMode()) {
  227. if (crn == 0 && opcode_1 == 0) {
  228. if (crm == 0) {
  229. if (opcode_2 == 0)
  230. return CP15[CP15_MAIN_ID];
  231. if (opcode_2 == 1)
  232. return CP15[CP15_CACHE_TYPE];
  233. if (opcode_2 == 3)
  234. return CP15[CP15_TLB_TYPE];
  235. if (opcode_2 == 5)
  236. return CP15[CP15_CPU_ID];
  237. } else if (crm == 1) {
  238. if (opcode_2 == 0)
  239. return CP15[CP15_PROCESSOR_FEATURE_0];
  240. if (opcode_2 == 1)
  241. return CP15[CP15_PROCESSOR_FEATURE_1];
  242. if (opcode_2 == 2)
  243. return CP15[CP15_DEBUG_FEATURE_0];
  244. if (opcode_2 == 4)
  245. return CP15[CP15_MEMORY_MODEL_FEATURE_0];
  246. if (opcode_2 == 5)
  247. return CP15[CP15_MEMORY_MODEL_FEATURE_1];
  248. if (opcode_2 == 6)
  249. return CP15[CP15_MEMORY_MODEL_FEATURE_2];
  250. if (opcode_2 == 7)
  251. return CP15[CP15_MEMORY_MODEL_FEATURE_3];
  252. } else if (crm == 2) {
  253. if (opcode_2 == 0)
  254. return CP15[CP15_ISA_FEATURE_0];
  255. if (opcode_2 == 1)
  256. return CP15[CP15_ISA_FEATURE_1];
  257. if (opcode_2 == 2)
  258. return CP15[CP15_ISA_FEATURE_2];
  259. if (opcode_2 == 3)
  260. return CP15[CP15_ISA_FEATURE_3];
  261. if (opcode_2 == 4)
  262. return CP15[CP15_ISA_FEATURE_4];
  263. }
  264. }
  265. if (crn == 1 && opcode_1 == 0 && crm == 0) {
  266. if (opcode_2 == 0)
  267. return CP15[CP15_CONTROL];
  268. if (opcode_2 == 1)
  269. return CP15[CP15_AUXILIARY_CONTROL];
  270. if (opcode_2 == 2)
  271. return CP15[CP15_COPROCESSOR_ACCESS_CONTROL];
  272. }
  273. if (crn == 2 && opcode_1 == 0 && crm == 0) {
  274. if (opcode_2 == 0)
  275. return CP15[CP15_TRANSLATION_BASE_TABLE_0];
  276. if (opcode_2 == 1)
  277. return CP15[CP15_TRANSLATION_BASE_TABLE_1];
  278. if (opcode_2 == 2)
  279. return CP15[CP15_TRANSLATION_BASE_CONTROL];
  280. }
  281. if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
  282. return CP15[CP15_DOMAIN_ACCESS_CONTROL];
  283. if (crn == 5 && opcode_1 == 0 && crm == 0) {
  284. if (opcode_2 == 0)
  285. return CP15[CP15_FAULT_STATUS];
  286. if (opcode_2 == 1)
  287. return CP15[CP15_INSTR_FAULT_STATUS];
  288. }
  289. if (crn == 6 && opcode_1 == 0 && crm == 0) {
  290. if (opcode_2 == 0)
  291. return CP15[CP15_FAULT_ADDRESS];
  292. if (opcode_2 == 1)
  293. return CP15[CP15_WFAR];
  294. }
  295. if (crn == 7 && opcode_1 == 0 && crm == 4 && opcode_2 == 0)
  296. return CP15[CP15_PHYS_ADDRESS];
  297. if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
  298. return CP15[CP15_DATA_CACHE_LOCKDOWN];
  299. if (crn == 10 && opcode_1 == 0) {
  300. if (crm == 0 && opcode_2 == 0)
  301. return CP15[CP15_TLB_LOCKDOWN];
  302. if (crm == 2) {
  303. if (opcode_2 == 0)
  304. return CP15[CP15_PRIMARY_REGION_REMAP];
  305. if (opcode_2 == 1)
  306. return CP15[CP15_NORMAL_REGION_REMAP];
  307. }
  308. }
  309. if (crn == 13 && crm == 0) {
  310. if (opcode_2 == 0)
  311. return CP15[CP15_PID];
  312. if (opcode_2 == 1)
  313. return CP15[CP15_CONTEXT_ID];
  314. if (opcode_2 == 4)
  315. return CP15[CP15_THREAD_PRW];
  316. }
  317. if (crn == 15) {
  318. if (opcode_1 == 0 && crm == 12) {
  319. if (opcode_2 == 0)
  320. return CP15[CP15_PERFORMANCE_MONITOR_CONTROL];
  321. if (opcode_2 == 1)
  322. return CP15[CP15_CYCLE_COUNTER];
  323. if (opcode_2 == 2)
  324. return CP15[CP15_COUNT_0];
  325. if (opcode_2 == 3)
  326. return CP15[CP15_COUNT_1];
  327. }
  328. if (opcode_1 == 5 && opcode_2 == 2) {
  329. if (crm == 5)
  330. return CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS];
  331. if (crm == 6)
  332. return CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS];
  333. if (crm == 7)
  334. return CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE];
  335. }
  336. if (opcode_1 == 7 && crm == 1 && opcode_2 == 0)
  337. return CP15[CP15_TLB_DEBUG_CONTROL];
  338. }
  339. }
  340. LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.",
  341. crn, crm, opcode_1, opcode_2);
  342. return 0;
  343. }
  344. // Write to the CP15 registers. Used with implementation of the MCR instruction.
  345. // Note that since the 3DS does not have the hypervisor extensions, these registers
  346. // are not implemented.
  347. void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) {
  348. if (InAPrivilegedMode()) {
  349. if (crn == 1 && opcode_1 == 0 && crm == 0) {
  350. if (opcode_2 == 0)
  351. CP15[CP15_CONTROL] = value;
  352. else if (opcode_2 == 1)
  353. CP15[CP15_AUXILIARY_CONTROL] = value;
  354. else if (opcode_2 == 2)
  355. CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value;
  356. } else if (crn == 2 && opcode_1 == 0 && crm == 0) {
  357. if (opcode_2 == 0)
  358. CP15[CP15_TRANSLATION_BASE_TABLE_0] = value;
  359. else if (opcode_2 == 1)
  360. CP15[CP15_TRANSLATION_BASE_TABLE_1] = value;
  361. else if (opcode_2 == 2)
  362. CP15[CP15_TRANSLATION_BASE_CONTROL] = value;
  363. } else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) {
  364. CP15[CP15_DOMAIN_ACCESS_CONTROL] = value;
  365. } else if (crn == 5 && opcode_1 == 0 && crm == 0) {
  366. if (opcode_2 == 0)
  367. CP15[CP15_FAULT_STATUS] = value;
  368. else if (opcode_2 == 1)
  369. CP15[CP15_INSTR_FAULT_STATUS] = value;
  370. } else if (crn == 6 && opcode_1 == 0 && crm == 0) {
  371. if (opcode_2 == 0)
  372. CP15[CP15_FAULT_ADDRESS] = value;
  373. else if (opcode_2 == 1)
  374. CP15[CP15_WFAR] = value;
  375. } else if (crn == 7 && opcode_1 == 0) {
  376. if (crm == 0 && opcode_2 == 4) {
  377. CP15[CP15_WAIT_FOR_INTERRUPT] = value;
  378. } else if (crm == 4 && opcode_2 == 0) {
  379. // NOTE: Not entirely accurate. This should do permission checks.
  380. CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value);
  381. } else if (crm == 5) {
  382. if (opcode_2 == 0)
  383. CP15[CP15_INVALIDATE_INSTR_CACHE] = value;
  384. else if (opcode_2 == 1)
  385. CP15[CP15_INVALIDATE_INSTR_CACHE_USING_MVA] = value;
  386. else if (opcode_2 == 2)
  387. CP15[CP15_INVALIDATE_INSTR_CACHE_USING_INDEX] = value;
  388. else if (opcode_2 == 6)
  389. CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value;
  390. else if (opcode_2 == 7)
  391. CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value;
  392. } else if (crm == 6) {
  393. if (opcode_2 == 0)
  394. CP15[CP15_INVALIDATE_DATA_CACHE] = value;
  395. else if (opcode_2 == 1)
  396. CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value;
  397. else if (opcode_2 == 2)
  398. CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
  399. } else if (crm == 7 && opcode_2 == 0) {
  400. CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value;
  401. } else if (crm == 10) {
  402. if (opcode_2 == 0)
  403. CP15[CP15_CLEAN_DATA_CACHE] = value;
  404. else if (opcode_2 == 1)
  405. CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value;
  406. else if (opcode_2 == 2)
  407. CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value;
  408. } else if (crm == 14) {
  409. if (opcode_2 == 0)
  410. CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value;
  411. else if (opcode_2 == 1)
  412. CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value;
  413. else if (opcode_2 == 2)
  414. CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
  415. }
  416. } else if (crn == 8 && opcode_1 == 0) {
  417. if (crm == 5) {
  418. if (opcode_2 == 0)
  419. CP15[CP15_INVALIDATE_ITLB] = value;
  420. else if (opcode_2 == 1)
  421. CP15[CP15_INVALIDATE_ITLB_SINGLE_ENTRY] = value;
  422. else if (opcode_2 == 2)
  423. CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value;
  424. else if (opcode_2 == 3)
  425. CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value;
  426. } else if (crm == 6) {
  427. if (opcode_2 == 0)
  428. CP15[CP15_INVALIDATE_DTLB] = value;
  429. else if (opcode_2 == 1)
  430. CP15[CP15_INVALIDATE_DTLB_SINGLE_ENTRY] = value;
  431. else if (opcode_2 == 2)
  432. CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value;
  433. else if (opcode_2 == 3)
  434. CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value;
  435. } else if (crm == 7) {
  436. if (opcode_2 == 0)
  437. CP15[CP15_INVALIDATE_UTLB] = value;
  438. else if (opcode_2 == 1)
  439. CP15[CP15_INVALIDATE_UTLB_SINGLE_ENTRY] = value;
  440. else if (opcode_2 == 2)
  441. CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH] = value;
  442. else if (opcode_2 == 3)
  443. CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value;
  444. }
  445. } else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) {
  446. CP15[CP15_DATA_CACHE_LOCKDOWN] = value;
  447. } else if (crn == 10 && opcode_1 == 0) {
  448. if (crm == 0 && opcode_2 == 0) {
  449. CP15[CP15_TLB_LOCKDOWN] = value;
  450. } else if (crm == 2) {
  451. if (opcode_2 == 0)
  452. CP15[CP15_PRIMARY_REGION_REMAP] = value;
  453. else if (opcode_2 == 1)
  454. CP15[CP15_NORMAL_REGION_REMAP] = value;
  455. }
  456. } else if (crn == 13 && opcode_1 == 0 && crm == 0) {
  457. if (opcode_2 == 0)
  458. CP15[CP15_PID] = value;
  459. else if (opcode_2 == 1)
  460. CP15[CP15_CONTEXT_ID] = value;
  461. else if (opcode_2 == 3)
  462. CP15[CP15_THREAD_URO] = value;
  463. else if (opcode_2 == 4)
  464. CP15[CP15_THREAD_PRW] = value;
  465. } else if (crn == 15) {
  466. if (opcode_1 == 0 && crm == 12) {
  467. if (opcode_2 == 0)
  468. CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value;
  469. else if (opcode_2 == 1)
  470. CP15[CP15_CYCLE_COUNTER] = value;
  471. else if (opcode_2 == 2)
  472. CP15[CP15_COUNT_0] = value;
  473. else if (opcode_2 == 3)
  474. CP15[CP15_COUNT_1] = value;
  475. } else if (opcode_1 == 5) {
  476. if (crm == 4) {
  477. if (opcode_2 == 2)
  478. CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value;
  479. else if (opcode_2 == 4)
  480. CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value;
  481. } else if (crm == 5 && opcode_2 == 2) {
  482. CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value;
  483. } else if (crm == 6 && opcode_2 == 2) {
  484. CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value;
  485. } else if (crm == 7 && opcode_2 == 2) {
  486. CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value;
  487. }
  488. } else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) {
  489. CP15[CP15_TLB_DEBUG_CONTROL] = value;
  490. }
  491. }
  492. }
  493. // Unprivileged registers
  494. if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) {
  495. CP15[CP15_FLUSH_PREFETCH_BUFFER] = value;
  496. } else if (crn == 7 && opcode_1 == 0 && crm == 10) {
  497. if (opcode_2 == 4)
  498. CP15[CP15_DATA_SYNC_BARRIER] = value;
  499. else if (opcode_2 == 5)
  500. CP15[CP15_DATA_MEMORY_BARRIER] = value;
  501. } else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) {
  502. CP15[CP15_THREAD_UPRW] = value;
  503. }
  504. }