armcopro.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /* armcopro.c -- co-processor interface: ARM6 Instruction Emulator.
  2. Copyright (C) 1994, 2000 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/arm/skyeye_common/armdefs.h"
  15. #include "core/arm/skyeye_common/armemu.h"
  16. #include "core/arm/skyeye_common/vfp/vfp.h"
  17. //chy 2005-07-08
  18. //#include "ansidecl.h"
  19. //chy -------
  20. //#include "iwmmxt.h"
  21. /* Dummy Co-processors. */
  22. static unsigned
  23. NoCoPro3R(ARMul_State * state,
  24. unsigned a, ARMword b)
  25. {
  26. return ARMul_CANT;
  27. }
  28. static unsigned
  29. NoCoPro4R(ARMul_State * state,
  30. unsigned a,
  31. ARMword b, ARMword c)
  32. {
  33. return ARMul_CANT;
  34. }
  35. static unsigned
  36. NoCoPro4W(ARMul_State * state,
  37. unsigned a,
  38. ARMword b, ARMword * c)
  39. {
  40. return ARMul_CANT;
  41. }
  42. static unsigned
  43. NoCoPro5R(ARMul_State * state,
  44. unsigned a,
  45. ARMword b,
  46. ARMword c, ARMword d)
  47. {
  48. return ARMul_CANT;
  49. }
  50. static unsigned
  51. NoCoPro5W(ARMul_State * state,
  52. unsigned a,
  53. ARMword b,
  54. ARMword * c, ARMword * d)
  55. {
  56. return ARMul_CANT;
  57. }
  58. /* The XScale Co-processors. */
  59. /* Coprocessor 15: System Control. */
  60. static void write_cp14_reg(unsigned, ARMword);
  61. static ARMword read_cp14_reg(unsigned);
  62. /* Check an access to a register. */
  63. static unsigned
  64. check_cp15_access(ARMul_State * state,
  65. unsigned reg,
  66. unsigned CRm, unsigned opcode_1, unsigned opcode_2)
  67. {
  68. /* Do not allow access to these register in USER mode. */
  69. //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
  70. if (state->Mode == USER26MODE || state->Mode == USER32MODE)
  71. return ARMul_CANT;
  72. /* Opcode_1should be zero. */
  73. if (opcode_1 != 0)
  74. return ARMul_CANT;
  75. /* Different register have different access requirements. */
  76. switch (reg) {
  77. case 0:
  78. case 1:
  79. /* CRm must be 0. Opcode_2 can be anything. */
  80. if (CRm != 0)
  81. return ARMul_CANT;
  82. break;
  83. case 2:
  84. case 3:
  85. /* CRm must be 0. Opcode_2 must be zero. */
  86. if ((CRm != 0) || (opcode_2 != 0))
  87. return ARMul_CANT;
  88. break;
  89. case 4:
  90. /* Access not allowed. */
  91. return ARMul_CANT;
  92. case 5:
  93. case 6:
  94. /* Opcode_2 must be zero. CRm must be 0. */
  95. if ((CRm != 0) || (opcode_2 != 0))
  96. return ARMul_CANT;
  97. break;
  98. case 7:
  99. /* Permissable combinations:
  100. Opcode_2 CRm
  101. 0 5
  102. 0 6
  103. 0 7
  104. 1 5
  105. 1 6
  106. 1 10
  107. 4 10
  108. 5 2
  109. 6 5 */
  110. switch (opcode_2) {
  111. default:
  112. return ARMul_CANT;
  113. case 6:
  114. if (CRm != 5)
  115. return ARMul_CANT;
  116. break;
  117. case 5:
  118. if (CRm != 2)
  119. return ARMul_CANT;
  120. break;
  121. case 4:
  122. if (CRm != 10)
  123. return ARMul_CANT;
  124. break;
  125. case 1:
  126. if ((CRm != 5) && (CRm != 6) && (CRm != 10))
  127. return ARMul_CANT;
  128. break;
  129. case 0:
  130. if ((CRm < 5) || (CRm > 7))
  131. return ARMul_CANT;
  132. break;
  133. }
  134. break;
  135. case 8:
  136. /* Permissable combinations:
  137. Opcode_2 CRm
  138. 0 5
  139. 0 6
  140. 0 7
  141. 1 5
  142. 1 6 */
  143. if (opcode_2 > 1)
  144. return ARMul_CANT;
  145. if ((CRm < 5) || (CRm > 7))
  146. return ARMul_CANT;
  147. if (opcode_2 == 1 && CRm == 7)
  148. return ARMul_CANT;
  149. break;
  150. case 9:
  151. /* Opcode_2 must be zero or one. CRm must be 1 or 2. */
  152. if (((CRm != 0) && (CRm != 1))
  153. || ((opcode_2 != 1) && (opcode_2 != 2)))
  154. return ARMul_CANT;
  155. break;
  156. case 10:
  157. /* Opcode_2 must be zero or one. CRm must be 4 or 8. */
  158. if (((CRm != 0) && (CRm != 1))
  159. || ((opcode_2 != 4) && (opcode_2 != 8)))
  160. return ARMul_CANT;
  161. break;
  162. case 11:
  163. /* Access not allowed. */
  164. return ARMul_CANT;
  165. case 12:
  166. /* Access not allowed. */
  167. return ARMul_CANT;
  168. case 13:
  169. /* Opcode_2 must be zero. CRm must be 0. */
  170. if ((CRm != 0) || (opcode_2 != 0))
  171. return ARMul_CANT;
  172. break;
  173. case 14:
  174. /* Opcode_2 must be 0. CRm must be 0, 3, 4, 8 or 9. */
  175. if (opcode_2 != 0)
  176. return ARMul_CANT;
  177. if ((CRm != 0) && (CRm != 3) && (CRm != 4) && (CRm != 8)
  178. && (CRm != 9))
  179. return ARMul_CANT;
  180. break;
  181. case 15:
  182. /* Opcode_2 must be zero. CRm must be 1. */
  183. if ((CRm != 1) || (opcode_2 != 0))
  184. return ARMul_CANT;
  185. break;
  186. default:
  187. /* Should never happen. */
  188. return ARMul_CANT;
  189. }
  190. return ARMul_DONE;
  191. }
  192. /* Install co-processor instruction handlers in this routine. */
  193. unsigned
  194. ARMul_CoProInit(ARMul_State * state)
  195. {
  196. unsigned int i;
  197. /* Initialise tham all first. */
  198. for (i = 0; i < 16; i++)
  199. ARMul_CoProDetach(state, i);
  200. /* Install CoPro Instruction handlers here.
  201. The format is:
  202. ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
  203. LDC routine, STC routine, MRC routine, MCR routine,
  204. CDP routine, Read Reg routine, Write Reg routine). */
  205. if (state->is_v6) {
  206. ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
  207. VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
  208. ARMul_CoProAttach(state, 11, VFPInit, NULL, VFPLDC, VFPSTC,
  209. VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
  210. /*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
  211. MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);*/
  212. }
  213. //chy 2003-09-03 do it in future!!!!????
  214. #if 0
  215. if (state->is_iWMMXt) {
  216. ARMul_CoProAttach(state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC,
  217. NULL, NULL, IwmmxtCDP, NULL, NULL);
  218. ARMul_CoProAttach(state, 1, NULL, NULL, NULL, NULL,
  219. IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL,
  220. NULL);
  221. }
  222. #endif
  223. /* No handlers below here. */
  224. /* Call all the initialisation routines. */
  225. for (i = 0; i < 16; i++)
  226. if (state->CPInit[i])
  227. (state->CPInit[i]) (state);
  228. return TRUE;
  229. }
  230. /* Install co-processor finalisation routines in this routine. */
  231. void
  232. ARMul_CoProExit(ARMul_State * state)
  233. {
  234. register unsigned i;
  235. for (i = 0; i < 16; i++)
  236. if (state->CPExit[i])
  237. (state->CPExit[i]) (state);
  238. for (i = 0; i < 16; i++) /* Detach all handlers. */
  239. ARMul_CoProDetach(state, i);
  240. }
  241. /* Routines to hook Co-processors into ARMulator. */
  242. void
  243. ARMul_CoProAttach(ARMul_State * state,
  244. unsigned number,
  245. ARMul_CPInits * init,
  246. ARMul_CPExits * exit,
  247. ARMul_LDCs * ldc,
  248. ARMul_STCs * stc,
  249. ARMul_MRCs * mrc,
  250. ARMul_MCRs * mcr,
  251. ARMul_MRRCs * mrrc,
  252. ARMul_MCRRs * mcrr,
  253. ARMul_CDPs * cdp,
  254. ARMul_CPReads * read, ARMul_CPWrites * write)
  255. {
  256. if (init != NULL)
  257. state->CPInit[number] = init;
  258. if (exit != NULL)
  259. state->CPExit[number] = exit;
  260. if (ldc != NULL)
  261. state->LDC[number] = ldc;
  262. if (stc != NULL)
  263. state->STC[number] = stc;
  264. if (mrc != NULL)
  265. state->MRC[number] = mrc;
  266. if (mcr != NULL)
  267. state->MCR[number] = mcr;
  268. if (mrrc != NULL)
  269. state->MRRC[number] = mrrc;
  270. if (mcrr != NULL)
  271. state->MCRR[number] = mcrr;
  272. if (cdp != NULL)
  273. state->CDP[number] = cdp;
  274. if (read != NULL)
  275. state->CPRead[number] = read;
  276. if (write != NULL)
  277. state->CPWrite[number] = write;
  278. }
  279. void
  280. ARMul_CoProDetach(ARMul_State * state, unsigned number)
  281. {
  282. ARMul_CoProAttach(state, number, NULL, NULL,
  283. NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
  284. NoCoPro5W, NoCoPro5R, NoCoPro3R, NULL, NULL);
  285. state->CPInit[number] = NULL;
  286. state->CPExit[number] = NULL;
  287. state->CPRead[number] = NULL;
  288. state->CPWrite[number] = NULL;
  289. }