armsupp.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator.
  2. Copyright (C) 1994 Advanced RISC Machines Ltd.
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  14. #include "common/logging/log.h"
  15. #include "core/mem_map.h"
  16. #include "core/arm/skyeye_common/armdefs.h"
  17. #include "core/arm/skyeye_common/arm_regformat.h"
  18. // Unsigned sum of absolute difference
  19. u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
  20. {
  21. if (left > right)
  22. return left - right;
  23. return right - left;
  24. }
  25. // Add with carry, indicates if a carry-out or signed overflow occurred.
  26. u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred)
  27. {
  28. u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in;
  29. s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in;
  30. u64 result = (unsigned_sum & 0xFFFFFFFF);
  31. if (carry_out_occurred)
  32. *carry_out_occurred = (result != unsigned_sum);
  33. if (overflow_occurred)
  34. *overflow_occurred = ((s64)(s32)result != signed_sum);
  35. return (u32)result;
  36. }
  37. // Compute whether an addition of A and B, giving RESULT, overflowed.
  38. bool AddOverflow(ARMword a, ARMword b, ARMword result)
  39. {
  40. return ((NEG(a) && NEG(b) && POS(result)) ||
  41. (POS(a) && POS(b) && NEG(result)));
  42. }
  43. // Compute whether a subtraction of A and B, giving RESULT, overflowed.
  44. bool SubOverflow(ARMword a, ARMword b, ARMword result)
  45. {
  46. return ((NEG(a) && POS(b) && POS(result)) ||
  47. (POS(a) && NEG(b) && NEG(result)));
  48. }
  49. // Returns true if the Q flag should be set as a result of overflow.
  50. bool ARMul_AddOverflowQ(ARMword a, ARMword b)
  51. {
  52. u32 result = a + b;
  53. if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0)
  54. return true;
  55. return false;
  56. }
  57. // 8-bit signed saturated addition
  58. u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
  59. {
  60. u8 result = left + right;
  61. if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) {
  62. if (left & 0x80)
  63. result = 0x80;
  64. else
  65. result = 0x7F;
  66. }
  67. return result;
  68. }
  69. // 8-bit signed saturated subtraction
  70. u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
  71. {
  72. u8 result = left - right;
  73. if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) {
  74. if (left & 0x80)
  75. result = 0x80;
  76. else
  77. result = 0x7F;
  78. }
  79. return result;
  80. }
  81. // 16-bit signed saturated addition
  82. u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
  83. {
  84. u16 result = left + right;
  85. if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) {
  86. if (left & 0x8000)
  87. result = 0x8000;
  88. else
  89. result = 0x7FFF;
  90. }
  91. return result;
  92. }
  93. // 16-bit signed saturated subtraction
  94. u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
  95. {
  96. u16 result = left - right;
  97. if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) {
  98. if (left & 0x8000)
  99. result = 0x8000;
  100. else
  101. result = 0x7FFF;
  102. }
  103. return result;
  104. }
  105. // 8-bit unsigned saturated addition
  106. u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
  107. {
  108. u8 result = left + right;
  109. if (result < left)
  110. result = 0xFF;
  111. return result;
  112. }
  113. // 16-bit unsigned saturated addition
  114. u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
  115. {
  116. u16 result = left + right;
  117. if (result < left)
  118. result = 0xFFFF;
  119. return result;
  120. }
  121. // 8-bit unsigned saturated subtraction
  122. u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
  123. {
  124. if (left <= right)
  125. return 0;
  126. return left - right;
  127. }
  128. // 16-bit unsigned saturated subtraction
  129. u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
  130. {
  131. if (left <= right)
  132. return 0;
  133. return left - right;
  134. }
  135. // Signed saturation.
  136. u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
  137. {
  138. const u32 max = (1 << shift) - 1;
  139. const s32 top = (value >> shift);
  140. if (top > 0) {
  141. *saturation_occurred = true;
  142. return max;
  143. }
  144. else if (top < -1) {
  145. *saturation_occurred = true;
  146. return ~max;
  147. }
  148. *saturation_occurred = false;
  149. return (u32)value;
  150. }
  151. // Unsigned saturation
  152. u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
  153. {
  154. const u32 max = (1 << shift) - 1;
  155. if (value < 0) {
  156. *saturation_occurred = true;
  157. return 0;
  158. } else if ((u32)value > max) {
  159. *saturation_occurred = true;
  160. return max;
  161. }
  162. *saturation_occurred = false;
  163. return (u32)value;
  164. }
  165. // Whether or not the given CPU is in big endian mode (E bit is set)
  166. bool InBigEndianMode(ARMul_State* cpu)
  167. {
  168. return (cpu->Cpsr & (1 << 9)) != 0;
  169. }
  170. // Whether or not the given CPU is in a mode other than user mode.
  171. bool InAPrivilegedMode(ARMul_State* cpu)
  172. {
  173. return (cpu->Mode != USER32MODE);
  174. }
  175. // Reads from the CP15 registers. Used with implementation of the MRC instruction.
  176. // Note that since the 3DS does not have the hypervisor extensions, these registers
  177. // are not implemented.
  178. u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
  179. {
  180. // Unprivileged registers
  181. if (crn == 13 && opcode_1 == 0 && crm == 0)
  182. {
  183. if (opcode_2 == 2)
  184. return cpu->CP15[CP15_THREAD_UPRW];
  185. if (opcode_2 == 3)
  186. return cpu->CP15[CP15_THREAD_URO];
  187. }
  188. if (InAPrivilegedMode(cpu))
  189. {
  190. if (crn == 0 && opcode_1 == 0)
  191. {
  192. if (crm == 0)
  193. {
  194. if (opcode_2 == 0)
  195. return cpu->CP15[CP15_MAIN_ID];
  196. if (opcode_2 == 1)
  197. return cpu->CP15[CP15_CACHE_TYPE];
  198. if (opcode_2 == 3)
  199. return cpu->CP15[CP15_TLB_TYPE];
  200. if (opcode_2 == 5)
  201. return cpu->CP15[CP15_CPU_ID];
  202. }
  203. else if (crm == 1)
  204. {
  205. if (opcode_2 == 0)
  206. return cpu->CP15[CP15_PROCESSOR_FEATURE_0];
  207. if (opcode_2 == 1)
  208. return cpu->CP15[CP15_PROCESSOR_FEATURE_1];
  209. if (opcode_2 == 2)
  210. return cpu->CP15[CP15_DEBUG_FEATURE_0];
  211. if (opcode_2 == 4)
  212. return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_0];
  213. if (opcode_2 == 5)
  214. return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_1];
  215. if (opcode_2 == 6)
  216. return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_2];
  217. if (opcode_2 == 7)
  218. return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_3];
  219. }
  220. else if (crm == 2)
  221. {
  222. if (opcode_2 == 0)
  223. return cpu->CP15[CP15_ISA_FEATURE_0];
  224. if (opcode_2 == 1)
  225. return cpu->CP15[CP15_ISA_FEATURE_1];
  226. if (opcode_2 == 2)
  227. return cpu->CP15[CP15_ISA_FEATURE_2];
  228. if (opcode_2 == 3)
  229. return cpu->CP15[CP15_ISA_FEATURE_3];
  230. if (opcode_2 == 4)
  231. return cpu->CP15[CP15_ISA_FEATURE_4];
  232. }
  233. }
  234. if (crn == 1 && opcode_1 == 0 && crm == 0)
  235. {
  236. if (opcode_2 == 0)
  237. return cpu->CP15[CP15_CONTROL];
  238. if (opcode_2 == 1)
  239. return cpu->CP15[CP15_AUXILIARY_CONTROL];
  240. if (opcode_2 == 2)
  241. return cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL];
  242. }
  243. if (crn == 2 && opcode_1 == 0 && crm == 0)
  244. {
  245. if (opcode_2 == 0)
  246. return cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0];
  247. if (opcode_2 == 1)
  248. return cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1];
  249. if (opcode_2 == 2)
  250. return cpu->CP15[CP15_TRANSLATION_BASE_CONTROL];
  251. }
  252. if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
  253. return cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL];
  254. if (crn == 5 && opcode_1 == 0 && crm == 0)
  255. {
  256. if (opcode_2 == 0)
  257. return cpu->CP15[CP15_FAULT_STATUS];
  258. if (opcode_2 == 1)
  259. return cpu->CP15[CP15_INSTR_FAULT_STATUS];
  260. }
  261. if (crn == 6 && opcode_1 == 0 && crm == 0)
  262. {
  263. if (opcode_2 == 0)
  264. return cpu->CP15[CP15_FAULT_ADDRESS];
  265. if (opcode_2 == 1)
  266. return cpu->CP15[CP15_WFAR];
  267. }
  268. if (crn == 7 && opcode_1 == 0 && crm == 4 && opcode_2 == 0)
  269. return cpu->CP15[CP15_PHYS_ADDRESS];
  270. if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
  271. return cpu->CP15[CP15_DATA_CACHE_LOCKDOWN];
  272. if (crn == 10 && opcode_1 == 0)
  273. {
  274. if (crm == 0 && opcode_2 == 0)
  275. return cpu->CP15[CP15_TLB_LOCKDOWN];
  276. if (crm == 2)
  277. {
  278. if (opcode_2 == 0)
  279. return cpu->CP15[CP15_PRIMARY_REGION_REMAP];
  280. if (opcode_2 == 1)
  281. return cpu->CP15[CP15_NORMAL_REGION_REMAP];
  282. }
  283. }
  284. if (crn == 13 && crm == 0)
  285. {
  286. if (opcode_2 == 0)
  287. return cpu->CP15[CP15_PID];
  288. if (opcode_2 == 1)
  289. return cpu->CP15[CP15_CONTEXT_ID];
  290. if (opcode_2 == 4)
  291. return cpu->CP15[CP15_THREAD_PRW];
  292. }
  293. if (crn == 15)
  294. {
  295. if (opcode_1 == 0 && crm == 12)
  296. {
  297. if (opcode_2 == 0)
  298. return cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL];
  299. if (opcode_2 == 1)
  300. return cpu->CP15[CP15_CYCLE_COUNTER];
  301. if (opcode_2 == 2)
  302. return cpu->CP15[CP15_COUNT_0];
  303. if (opcode_2 == 3)
  304. return cpu->CP15[CP15_COUNT_1];
  305. }
  306. if (opcode_1 == 5 && opcode_2 == 2)
  307. {
  308. if (crm == 5)
  309. return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS];
  310. if (crm == 6)
  311. return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS];
  312. if (crm == 7)
  313. return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE];
  314. }
  315. if (opcode_1 == 7 && crm == 1 && opcode_2 == 0)
  316. return cpu->CP15[CP15_TLB_DEBUG_CONTROL];
  317. }
  318. }
  319. LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2);
  320. return 0;
  321. }
  322. // Write to the CP15 registers. Used with implementation of the MCR instruction.
  323. // Note that since the 3DS does not have the hypervisor extensions, these registers
  324. // are not implemented.
  325. void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
  326. {
  327. if (InAPrivilegedMode(cpu))
  328. {
  329. if (crn == 1 && opcode_1 == 0 && crm == 0)
  330. {
  331. if (opcode_2 == 0)
  332. cpu->CP15[CP15_CONTROL] = value;
  333. else if (opcode_2 == 1)
  334. cpu->CP15[CP15_AUXILIARY_CONTROL] = value;
  335. else if (opcode_2 == 2)
  336. cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value;
  337. }
  338. else if (crn == 2 && opcode_1 == 0 && crm == 0)
  339. {
  340. if (opcode_2 == 0)
  341. cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0] = value;
  342. else if (opcode_2 == 1)
  343. cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1] = value;
  344. else if (opcode_2 == 2)
  345. cpu->CP15[CP15_TRANSLATION_BASE_CONTROL] = value;
  346. }
  347. else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
  348. {
  349. cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL] = value;
  350. }
  351. else if (crn == 5 && opcode_1 == 0 && crm == 0)
  352. {
  353. if (opcode_2 == 0)
  354. cpu->CP15[CP15_FAULT_STATUS] = value;
  355. else if (opcode_2 == 1)
  356. cpu->CP15[CP15_INSTR_FAULT_STATUS] = value;
  357. }
  358. else if (crn == 6 && opcode_1 == 0 && crm == 0)
  359. {
  360. if (opcode_2 == 0)
  361. cpu->CP15[CP15_FAULT_ADDRESS] = value;
  362. else if (opcode_2 == 1)
  363. cpu->CP15[CP15_WFAR] = value;
  364. }
  365. else if (crn == 7 && opcode_1 == 0)
  366. {
  367. if (crm == 0 && opcode_2 == 4)
  368. {
  369. cpu->CP15[CP15_WAIT_FOR_INTERRUPT] = value;
  370. }
  371. else if (crm == 4 && opcode_2 == 0)
  372. {
  373. // NOTE: Not entirely accurate. This should do permission checks.
  374. cpu->CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value);
  375. }
  376. else if (crm == 5)
  377. {
  378. if (opcode_2 == 0)
  379. cpu->CP15[CP15_INVALIDATE_INSTR_CACHE] = value;
  380. else if (opcode_2 == 1)
  381. cpu->CP15[CP15_INVALIDATE_INSTR_CACHE_USING_MVA] = value;
  382. else if (opcode_2 == 2)
  383. cpu->CP15[CP15_INVALIDATE_INSTR_CACHE_USING_INDEX] = value;
  384. else if (opcode_2 == 6)
  385. cpu->CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value;
  386. else if (opcode_2 == 7)
  387. cpu->CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value;
  388. }
  389. else if (crm == 6)
  390. {
  391. if (opcode_2 == 0)
  392. cpu->CP15[CP15_INVALIDATE_DATA_CACHE] = value;
  393. else if (opcode_2 == 1)
  394. cpu->CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value;
  395. else if (opcode_2 == 2)
  396. cpu->CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
  397. }
  398. else if (crm == 7 && opcode_2 == 0)
  399. {
  400. cpu->CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value;
  401. }
  402. else if (crm == 10)
  403. {
  404. if (opcode_2 == 0)
  405. cpu->CP15[CP15_CLEAN_DATA_CACHE] = value;
  406. else if (opcode_2 == 1)
  407. cpu->CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value;
  408. else if (opcode_2 == 2)
  409. cpu->CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value;
  410. }
  411. else if (crm == 14)
  412. {
  413. if (opcode_2 == 0)
  414. cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value;
  415. else if (opcode_2 == 1)
  416. cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value;
  417. else if (opcode_2 == 2)
  418. cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
  419. }
  420. }
  421. else if (crn == 8 && opcode_1 == 0)
  422. {
  423. LOG_WARNING(Core_ARM11, "TLB operations not fully implemented.");
  424. if (crm == 5)
  425. {
  426. if (opcode_2 == 0)
  427. cpu->CP15[CP15_INVALIDATE_ITLB] = value;
  428. else if (opcode_2 == 1)
  429. cpu->CP15[CP15_INVALIDATE_ITLB_SINGLE_ENTRY] = value;
  430. else if (opcode_2 == 2)
  431. cpu->CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value;
  432. else if (opcode_2 == 3)
  433. cpu->CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value;
  434. }
  435. else if (crm == 6)
  436. {
  437. if (opcode_2 == 0)
  438. cpu->CP15[CP15_INVALIDATE_DTLB] = value;
  439. else if (opcode_2 == 1)
  440. cpu->CP15[CP15_INVALIDATE_DTLB_SINGLE_ENTRY] = value;
  441. else if (opcode_2 == 2)
  442. cpu->CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value;
  443. else if (opcode_2 == 3)
  444. cpu->CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value;
  445. }
  446. else if (crm == 7)
  447. {
  448. if (opcode_2 == 0)
  449. cpu->CP15[CP15_INVALIDATE_UTLB] = value;
  450. else if (opcode_2 == 1)
  451. cpu->CP15[CP15_INVALIDATE_UTLB_SINGLE_ENTRY] = value;
  452. else if (opcode_2 == 2)
  453. cpu->CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH] = value;
  454. else if (opcode_2 == 3)
  455. cpu->CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value;
  456. }
  457. }
  458. else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
  459. {
  460. cpu->CP15[CP15_DATA_CACHE_LOCKDOWN] = value;
  461. }
  462. else if (crn == 10 && opcode_1 == 0)
  463. {
  464. if (crm == 0 && opcode_2 == 0)
  465. {
  466. cpu->CP15[CP15_TLB_LOCKDOWN] = value;
  467. }
  468. else if (crm == 2)
  469. {
  470. if (opcode_2 == 0)
  471. cpu->CP15[CP15_PRIMARY_REGION_REMAP] = value;
  472. else if (opcode_2 == 1)
  473. cpu->CP15[CP15_NORMAL_REGION_REMAP] = value;
  474. }
  475. }
  476. else if (crn == 13 && opcode_1 == 0 && crm == 0)
  477. {
  478. if (opcode_2 == 0)
  479. cpu->CP15[CP15_PID] = value;
  480. else if (opcode_2 == 1)
  481. cpu->CP15[CP15_CONTEXT_ID] = value;
  482. else if (opcode_2 == 3)
  483. cpu->CP15[CP15_THREAD_URO] = value;
  484. else if (opcode_2 == 4)
  485. cpu->CP15[CP15_THREAD_PRW] = value;
  486. }
  487. else if (crn == 15)
  488. {
  489. if (opcode_1 == 0 && crm == 12)
  490. {
  491. if (opcode_2 == 0)
  492. cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value;
  493. else if (opcode_2 == 1)
  494. cpu->CP15[CP15_CYCLE_COUNTER] = value;
  495. else if (opcode_2 == 2)
  496. cpu->CP15[CP15_COUNT_0] = value;
  497. else if (opcode_2 == 3)
  498. cpu->CP15[CP15_COUNT_1] = value;
  499. }
  500. else if (opcode_1 == 5)
  501. {
  502. if (crm == 4)
  503. {
  504. if (opcode_2 == 2)
  505. cpu->CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value;
  506. else if (opcode_2 == 4)
  507. cpu->CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value;
  508. }
  509. else if (crm == 5 && opcode_2 == 2)
  510. {
  511. cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value;
  512. }
  513. else if (crm == 6 && opcode_2 == 2)
  514. {
  515. cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value;
  516. }
  517. else if (crm == 7 && opcode_2 == 2)
  518. {
  519. cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value;
  520. }
  521. }
  522. else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0)
  523. {
  524. cpu->CP15[CP15_TLB_DEBUG_CONTROL] = value;
  525. }
  526. }
  527. }
  528. // Unprivileged registers
  529. if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4)
  530. {
  531. cpu->CP15[CP15_FLUSH_PREFETCH_BUFFER] = value;
  532. }
  533. else if (crn == 7 && opcode_1 == 0 && crm == 10)
  534. {
  535. if (opcode_2 == 4)
  536. cpu->CP15[CP15_DATA_SYNC_BARRIER] = value;
  537. else if (opcode_2 == 5)
  538. cpu->CP15[CP15_DATA_MEMORY_BARRIER] = value;
  539. }
  540. else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2)
  541. {
  542. cpu->CP15[CP15_THREAD_UPRW] = value;
  543. }
  544. }