armvirt.c 15 KB

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