armvirt.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. /* armvirt.c -- ARMulator virtual memory interace: 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 3 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, see <http://www.gnu.org/licenses/>. */
  13. /* This file contains a complete ARMulator memory model, modelling a
  14. "virtual memory" system. A much simpler model can be found in armfast.c,
  15. and that model goes faster too, but has a fixed amount of memory. This
  16. model's memory has 64K pages, allocated on demand from a 64K entry page
  17. table. The routines PutWord and GetWord implement this. Pages are never
  18. freed as they might be needed again. A single area of memory may be
  19. defined to generate aborts. */
  20. /* This must come before any other includes. */
  21. #include "defs.h"
  22. #include "armos.h"
  23. #include "armdefs.h"
  24. #include "ansidecl.h"
  25. #ifdef VALIDATE /* for running the validate suite */
  26. #define TUBE 48 * 1024 * 1024 /* write a char on the screen */
  27. #define ABORTS 1
  28. #endif
  29. /* #define ABORTS */
  30. #ifdef ABORTS /* the memory system will abort */
  31. /* For the old test suite Abort between 32 Kbytes and 32 Mbytes
  32. For the new test suite Abort between 8 Mbytes and 26 Mbytes */
  33. /* #define LOWABORT 32 * 1024
  34. #define HIGHABORT 32 * 1024 * 1024 */
  35. #define LOWABORT 8 * 1024 * 1024
  36. #define HIGHABORT 26 * 1024 * 1024
  37. #endif
  38. #undef PAGESIZE /* Cleanup system headers. */
  39. #define NUMPAGES 64 * 1024
  40. #define PAGESIZE 64 * 1024
  41. #define PAGEBITS 16
  42. #define OFFSETBITS 0xffff
  43. int SWI_vector_installed = FALSE;
  44. /***************************************************************************\
  45. * Get a Word from Virtual Memory, maybe allocating the page *
  46. \***************************************************************************/
  47. static ARMword
  48. GetWord (ARMul_State * state, ARMword address, int check)
  49. {
  50. ARMword page;
  51. ARMword offset;
  52. ARMword **pagetable;
  53. ARMword *pageptr;
  54. if (check && state->is_XScale)
  55. XScale_check_memacc (state, &address, 0);
  56. page = address >> PAGEBITS;
  57. offset = (address & OFFSETBITS) >> 2;
  58. pagetable = (ARMword **) state->MemDataPtr;
  59. pageptr = *(pagetable + page);
  60. if (pageptr == NULL)
  61. {
  62. pageptr = (ARMword *) malloc (PAGESIZE);
  63. if (pageptr == NULL)
  64. {
  65. perror ("ARMulator can't allocate VM page");
  66. exit (12);
  67. }
  68. *(pagetable + page) = pageptr;
  69. }
  70. return *(pageptr + offset);
  71. }
  72. /***************************************************************************\
  73. * Put a Word into Virtual Memory, maybe allocating the page *
  74. \***************************************************************************/
  75. static void
  76. PutWord (ARMul_State * state, ARMword address, ARMword data, int check)
  77. {
  78. ARMword page;
  79. ARMword offset;
  80. ARMword **pagetable;
  81. ARMword *pageptr;
  82. if (check && state->is_XScale)
  83. XScale_check_memacc (state, &address, 1);
  84. page = address >> PAGEBITS;
  85. offset = (address & OFFSETBITS) >> 2;
  86. pagetable = (ARMword **) state->MemDataPtr;
  87. pageptr = *(pagetable + page);
  88. if (pageptr == NULL)
  89. {
  90. pageptr = (ARMword *) malloc (PAGESIZE);
  91. if (pageptr == NULL)
  92. {
  93. perror ("ARMulator can't allocate VM page");
  94. exit (13);
  95. }
  96. *(pagetable + page) = pageptr;
  97. }
  98. if (address == 0x8)
  99. SWI_vector_installed = TRUE;
  100. *(pageptr + offset) = data;
  101. }
  102. /***************************************************************************\
  103. * Initialise the memory interface *
  104. \***************************************************************************/
  105. unsigned
  106. ARMul_MemoryInit (ARMul_State * state, unsigned long initmemsize)
  107. {
  108. ARMword **pagetable;
  109. unsigned page;
  110. if (initmemsize)
  111. state->MemSize = initmemsize;
  112. pagetable = (ARMword **) malloc (sizeof (ARMword *) * NUMPAGES);
  113. if (pagetable == NULL)
  114. return FALSE;
  115. for (page = 0; page < NUMPAGES; page++)
  116. *(pagetable + page) = NULL;
  117. state->MemDataPtr = (unsigned char *) pagetable;
  118. ARMul_ConsolePrint (state, ", 4 Gb memory");
  119. return TRUE;
  120. }
  121. /***************************************************************************\
  122. * Remove the memory interface *
  123. \***************************************************************************/
  124. void
  125. ARMul_MemoryExit (ARMul_State * state)
  126. {
  127. ARMword page;
  128. ARMword **pagetable;
  129. ARMword *pageptr;
  130. pagetable = (ARMword **) state->MemDataPtr;
  131. for (page = 0; page < NUMPAGES; page++)
  132. {
  133. pageptr = *(pagetable + page);
  134. if (pageptr != NULL)
  135. free ((char *) pageptr);
  136. }
  137. free ((char *) pagetable);
  138. return;
  139. }
  140. /***************************************************************************\
  141. * ReLoad Instruction *
  142. \***************************************************************************/
  143. ARMword
  144. ARMul_ReLoadInstr (ARMul_State * state, ARMword address, ARMword isize)
  145. {
  146. #ifdef ABORTS
  147. if (address >= LOWABORT && address < HIGHABORT)
  148. {
  149. ARMul_PREFETCHABORT (address);
  150. return ARMul_ABORTWORD;
  151. }
  152. else
  153. {
  154. ARMul_CLEARABORT;
  155. }
  156. #endif
  157. if ((isize == 2) && (address & 0x2))
  158. {
  159. /* We return the next two halfwords: */
  160. ARMword lo = GetWord (state, address, FALSE);
  161. ARMword hi = GetWord (state, address + 4, FALSE);
  162. if (state->bigendSig == HIGH)
  163. return (lo << 16) | (hi >> 16);
  164. else
  165. return ((hi & 0xFFFF) << 16) | (lo >> 16);
  166. }
  167. return GetWord (state, address, TRUE);
  168. }
  169. /***************************************************************************\
  170. * Load Instruction, Sequential Cycle *
  171. \***************************************************************************/
  172. ARMword ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize)
  173. {
  174. state->NumScycles++;
  175. return ARMul_ReLoadInstr (state, address, isize);
  176. }
  177. /***************************************************************************\
  178. * Load Instruction, Non Sequential Cycle *
  179. \***************************************************************************/
  180. ARMword ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize)
  181. {
  182. state->NumNcycles++;
  183. return ARMul_ReLoadInstr (state, address, isize);
  184. }
  185. /***************************************************************************\
  186. * Read Word (but don't tell anyone!) *
  187. \***************************************************************************/
  188. ARMword ARMul_ReadWord (ARMul_State * state, ARMword address)
  189. {
  190. #ifdef ABORTS
  191. if (address >= LOWABORT && address < HIGHABORT)
  192. {
  193. ARMul_DATAABORT (address);
  194. return ARMul_ABORTWORD;
  195. }
  196. else
  197. {
  198. ARMul_CLEARABORT;
  199. }
  200. #endif
  201. return GetWord (state, address, TRUE);
  202. }
  203. /***************************************************************************\
  204. * Load Word, Sequential Cycle *
  205. \***************************************************************************/
  206. ARMword ARMul_LoadWordS (ARMul_State * state, ARMword address)
  207. {
  208. state->NumScycles++;
  209. return ARMul_ReadWord (state, address);
  210. }
  211. /***************************************************************************\
  212. * Load Word, Non Sequential Cycle *
  213. \***************************************************************************/
  214. ARMword ARMul_LoadWordN (ARMul_State * state, ARMword address)
  215. {
  216. state->NumNcycles++;
  217. return ARMul_ReadWord (state, address);
  218. }
  219. /***************************************************************************\
  220. * Load Halfword, (Non Sequential Cycle) *
  221. \***************************************************************************/
  222. ARMword ARMul_LoadHalfWord (ARMul_State * state, ARMword address)
  223. {
  224. ARMword temp, offset;
  225. state->NumNcycles++;
  226. temp = ARMul_ReadWord (state, address);
  227. offset = (((ARMword) state->bigendSig * 2) ^ (address & 2)) << 3; /* bit offset into the word */
  228. return (temp >> offset) & 0xffff;
  229. }
  230. /***************************************************************************\
  231. * Read Byte (but don't tell anyone!) *
  232. \***************************************************************************/
  233. ARMword ARMul_ReadByte (ARMul_State * state, ARMword address)
  234. {
  235. ARMword temp, offset;
  236. temp = ARMul_ReadWord (state, address);
  237. offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3; /* bit offset into the word */
  238. return (temp >> offset & 0xffL);
  239. }
  240. /***************************************************************************\
  241. * Load Byte, (Non Sequential Cycle) *
  242. \***************************************************************************/
  243. ARMword ARMul_LoadByte (ARMul_State * state, ARMword address)
  244. {
  245. state->NumNcycles++;
  246. return ARMul_ReadByte (state, address);
  247. }
  248. /***************************************************************************\
  249. * Write Word (but don't tell anyone!) *
  250. \***************************************************************************/
  251. void
  252. ARMul_WriteWord (ARMul_State * state, ARMword address, ARMword data)
  253. {
  254. #ifdef ABORTS
  255. if (address >= LOWABORT && address < HIGHABORT)
  256. {
  257. ARMul_DATAABORT (address);
  258. return;
  259. }
  260. else
  261. {
  262. ARMul_CLEARABORT;
  263. }
  264. #endif
  265. PutWord (state, address, data, TRUE);
  266. }
  267. /***************************************************************************\
  268. * Store Word, Sequential Cycle *
  269. \***************************************************************************/
  270. void
  271. ARMul_StoreWordS (ARMul_State * state, ARMword address, ARMword data)
  272. {
  273. state->NumScycles++;
  274. ARMul_WriteWord (state, address, data);
  275. }
  276. /***************************************************************************\
  277. * Store Word, Non Sequential Cycle *
  278. \***************************************************************************/
  279. void
  280. ARMul_StoreWordN (ARMul_State * state, ARMword address, ARMword data)
  281. {
  282. state->NumNcycles++;
  283. ARMul_WriteWord (state, address, data);
  284. }
  285. /***************************************************************************\
  286. * Store HalfWord, (Non Sequential Cycle) *
  287. \***************************************************************************/
  288. void
  289. ARMul_StoreHalfWord (ARMul_State * state, ARMword address, ARMword data)
  290. {
  291. ARMword temp, offset;
  292. state->NumNcycles++;
  293. #ifdef VALIDATE
  294. if (address == TUBE)
  295. {
  296. if (data == 4)
  297. state->Emulate = FALSE;
  298. else
  299. (void) putc ((char) data, stderr); /* Write Char */
  300. return;
  301. }
  302. #endif
  303. temp = ARMul_ReadWord (state, address);
  304. offset = (((ARMword) state->bigendSig * 2) ^ (address & 2)) << 3; /* bit offset into the word */
  305. PutWord (state, address,
  306. (temp & ~(0xffffL << offset)) | ((data & 0xffffL) << offset),
  307. TRUE);
  308. }
  309. /***************************************************************************\
  310. * Write Byte (but don't tell anyone!) *
  311. \***************************************************************************/
  312. void
  313. ARMul_WriteByte (ARMul_State * state, ARMword address, ARMword data)
  314. {
  315. ARMword temp, offset;
  316. temp = ARMul_ReadWord (state, address);
  317. offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3; /* bit offset into the word */
  318. PutWord (state, address,
  319. (temp & ~(0xffL << offset)) | ((data & 0xffL) << offset),
  320. TRUE);
  321. }
  322. /***************************************************************************\
  323. * Store Byte, (Non Sequential Cycle) *
  324. \***************************************************************************/
  325. void
  326. ARMul_StoreByte (ARMul_State * state, ARMword address, ARMword data)
  327. {
  328. state->NumNcycles++;
  329. #ifdef VALIDATE
  330. if (address == TUBE)
  331. {
  332. if (data == 4)
  333. state->Emulate = FALSE;
  334. else
  335. (void) putc ((char) data, stderr); /* Write Char */
  336. return;
  337. }
  338. #endif
  339. ARMul_WriteByte (state, address, data);
  340. }
  341. /***************************************************************************\
  342. * Swap Word, (Two Non Sequential Cycles) *
  343. \***************************************************************************/
  344. ARMword ARMul_SwapWord (ARMul_State * state, ARMword address, ARMword data)
  345. {
  346. ARMword temp;
  347. state->NumNcycles++;
  348. temp = ARMul_ReadWord (state, address);
  349. state->NumNcycles++;
  350. PutWord (state, address, data, TRUE);
  351. return temp;
  352. }
  353. /***************************************************************************\
  354. * Swap Byte, (Two Non Sequential Cycles) *
  355. \***************************************************************************/
  356. ARMword ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data)
  357. {
  358. ARMword temp;
  359. temp = ARMul_LoadByte (state, address);
  360. ARMul_StoreByte (state, address, data);
  361. return temp;
  362. }
  363. /***************************************************************************\
  364. * Count I Cycles *
  365. \***************************************************************************/
  366. void
  367. ARMul_Icycles (ARMul_State * state, unsigned number, ARMword address ATTRIBUTE_UNUSED)
  368. {
  369. state->NumIcycles += number;
  370. ARMul_CLEARABORT;
  371. }
  372. /***************************************************************************\
  373. * Count C Cycles *
  374. \***************************************************************************/
  375. void
  376. ARMul_Ccycles (ARMul_State * state, unsigned number, ARMword address ATTRIBUTE_UNUSED)
  377. {
  378. state->NumCcycles += number;
  379. ARMul_CLEARABORT;
  380. }
  381. /* Read a byte. Do not check for alignment or access errors. */
  382. ARMword
  383. ARMul_SafeReadByte (ARMul_State * state, ARMword address)
  384. {
  385. ARMword temp, offset;
  386. temp = GetWord (state, address, FALSE);
  387. offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3;
  388. return (temp >> offset & 0xffL);
  389. }
  390. void
  391. ARMul_SafeWriteByte (ARMul_State * state, ARMword address, ARMword data)
  392. {
  393. ARMword temp, offset;
  394. temp = GetWord (state, address, FALSE);
  395. offset = (((ARMword) state->bigendSig * 3) ^ (address & 3)) << 3;
  396. PutWord (state, address,
  397. (temp & ~(0xffL << offset)) | ((data & 0xffL) << offset),
  398. FALSE);
  399. }