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