helper.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. /*
  2. * MIPS emulation helpers for qemu.
  3. *
  4. * Copyright (c) 2004-2005 Jocelyn Mayer
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <stdarg.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <inttypes.h>
  24. #include <signal.h>
  25. #include "cpu.h"
  26. enum {
  27. TLBRET_DIRTY = -4,
  28. TLBRET_INVALID = -3,
  29. TLBRET_NOMATCH = -2,
  30. TLBRET_BADADDR = -1,
  31. TLBRET_MATCH = 0
  32. };
  33. #if !defined(CONFIG_USER_ONLY)
  34. /* no MMU emulation */
  35. int no_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
  36. target_ulong address, int rw, int access_type)
  37. {
  38. *physical = address;
  39. *prot = PAGE_READ | PAGE_WRITE;
  40. return TLBRET_MATCH;
  41. }
  42. /* fixed mapping MMU emulation */
  43. int fixed_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
  44. target_ulong address, int rw, int access_type)
  45. {
  46. if (address <= (int32_t)0x7FFFFFFFUL) {
  47. if (!(env->CP0_Status & (1 << CP0St_ERL)))
  48. *physical = address + 0x40000000UL;
  49. else
  50. *physical = address;
  51. } else if (address <= (int32_t)0xBFFFFFFFUL)
  52. *physical = address & 0x1FFFFFFF;
  53. else
  54. *physical = address;
  55. *prot = PAGE_READ | PAGE_WRITE;
  56. return TLBRET_MATCH;
  57. }
  58. /* MIPS32/MIPS64 R4000-style MMU emulation */
  59. int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
  60. target_ulong address, int rw, int access_type)
  61. {
  62. uint8_t ASID = env->CP0_EntryHi & 0xFF;
  63. int i;
  64. for (i = 0; i < env->tlb->tlb_in_use; i++) {
  65. r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i];
  66. /* 1k pages are not supported. */
  67. target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
  68. target_ulong tag = address & ~mask;
  69. target_ulong VPN = tlb->VPN & ~mask;
  70. #if defined(TARGET_MIPS64)
  71. tag &= env->SEGMask;
  72. #endif
  73. /* Check ASID, virtual page number & size */
  74. if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
  75. /* TLB match */
  76. int n = !!(address & mask & ~(mask >> 1));
  77. /* Check access rights */
  78. if (!(n ? tlb->V1 : tlb->V0))
  79. return TLBRET_INVALID;
  80. if (rw == 0 || (n ? tlb->D1 : tlb->D0)) {
  81. *physical = tlb->PFN[n] | (address & (mask >> 1));
  82. *prot = PAGE_READ;
  83. if (n ? tlb->D1 : tlb->D0)
  84. *prot |= PAGE_WRITE;
  85. return TLBRET_MATCH;
  86. }
  87. return TLBRET_DIRTY;
  88. }
  89. }
  90. return TLBRET_NOMATCH;
  91. }
  92. static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
  93. int *prot, target_ulong address,
  94. int rw, int access_type)
  95. {
  96. /* User mode can only access useg/xuseg */
  97. int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM;
  98. int supervisor_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_SM;
  99. int kernel_mode = !user_mode && !supervisor_mode;
  100. #if defined(TARGET_MIPS64)
  101. int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
  102. int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
  103. int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
  104. #endif
  105. int ret = TLBRET_MATCH;
  106. #if 0
  107. qemu_log("user mode %d h %08x\n", user_mode, env->hflags);
  108. #endif
  109. if (address <= (int32_t)0x7FFFFFFFUL) {
  110. /* useg */
  111. if (env->CP0_Status & (1 << CP0St_ERL)) {
  112. *physical = address & 0xFFFFFFFF;
  113. *prot = PAGE_READ | PAGE_WRITE;
  114. } else {
  115. ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
  116. }
  117. #if defined(TARGET_MIPS64)
  118. } else if (address < 0x4000000000000000ULL) {
  119. /* xuseg */
  120. if (UX && address <= (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) {
  121. ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
  122. } else {
  123. ret = TLBRET_BADADDR;
  124. }
  125. } else if (address < 0x8000000000000000ULL) {
  126. /* xsseg */
  127. if ((supervisor_mode || kernel_mode) &&
  128. SX && address <= (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) {
  129. ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
  130. } else {
  131. ret = TLBRET_BADADDR;
  132. }
  133. } else if (address < 0xC000000000000000ULL) {
  134. /* xkphys */
  135. if (kernel_mode && KX &&
  136. (address & 0x07FFFFFFFFFFFFFFULL) <= env->PAMask) {
  137. *physical = address & env->PAMask;
  138. *prot = PAGE_READ | PAGE_WRITE;
  139. } else {
  140. ret = TLBRET_BADADDR;
  141. }
  142. } else if (address < 0xFFFFFFFF80000000ULL) {
  143. /* xkseg */
  144. if (kernel_mode && KX &&
  145. address <= (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) {
  146. ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
  147. } else {
  148. ret = TLBRET_BADADDR;
  149. }
  150. #endif
  151. } else if (address < (int32_t)0xA0000000UL) {
  152. /* kseg0 */
  153. if (kernel_mode) {
  154. *physical = address - (int32_t)0x80000000UL;
  155. *prot = PAGE_READ | PAGE_WRITE;
  156. } else {
  157. ret = TLBRET_BADADDR;
  158. }
  159. } else if (address < (int32_t)0xC0000000UL) {
  160. /* kseg1 */
  161. if (kernel_mode) {
  162. *physical = address - (int32_t)0xA0000000UL;
  163. *prot = PAGE_READ | PAGE_WRITE;
  164. } else {
  165. ret = TLBRET_BADADDR;
  166. }
  167. } else if (address < (int32_t)0xE0000000UL) {
  168. /* sseg (kseg2) */
  169. if (supervisor_mode || kernel_mode) {
  170. ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
  171. } else {
  172. ret = TLBRET_BADADDR;
  173. }
  174. } else {
  175. /* kseg3 */
  176. /* XXX: debug segment is not emulated */
  177. if (kernel_mode) {
  178. ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
  179. } else {
  180. ret = TLBRET_BADADDR;
  181. }
  182. }
  183. #if 0
  184. qemu_log(TARGET_FMT_lx " %d %d => " TARGET_FMT_lx " %d (%d)\n",
  185. address, rw, access_type, *physical, *prot, ret);
  186. #endif
  187. return ret;
  188. }
  189. #endif
  190. static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
  191. int rw, int tlb_error)
  192. {
  193. int exception = 0, error_code = 0;
  194. switch (tlb_error) {
  195. default:
  196. case TLBRET_BADADDR:
  197. /* Reference to kernel address from user mode or supervisor mode */
  198. /* Reference to supervisor address from user mode */
  199. if (rw)
  200. exception = EXCP_AdES;
  201. else
  202. exception = EXCP_AdEL;
  203. break;
  204. case TLBRET_NOMATCH:
  205. /* No TLB match for a mapped address */
  206. if (rw)
  207. exception = EXCP_TLBS;
  208. else
  209. exception = EXCP_TLBL;
  210. error_code = 1;
  211. break;
  212. case TLBRET_INVALID:
  213. /* TLB match with no valid bit */
  214. if (rw)
  215. exception = EXCP_TLBS;
  216. else
  217. exception = EXCP_TLBL;
  218. break;
  219. case TLBRET_DIRTY:
  220. /* TLB match but 'D' bit is cleared */
  221. exception = EXCP_LTLBL;
  222. break;
  223. }
  224. /* Raise exception */
  225. env->CP0_BadVAddr = address;
  226. env->CP0_Context = (env->CP0_Context & ~0x007fffff) |
  227. ((address >> 9) & 0x007ffff0);
  228. env->CP0_EntryHi =
  229. (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1));
  230. #if defined(TARGET_MIPS64)
  231. env->CP0_EntryHi &= env->SEGMask;
  232. env->CP0_XContext = (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) |
  233. ((address & 0xC00000000000ULL) >> (55 - env->SEGBITS)) |
  234. ((address & ((1ULL << env->SEGBITS) - 1) & 0xFFFFFFFFFFFFE000ULL) >> 9);
  235. #endif
  236. env->exception_index = exception;
  237. env->error_code = error_code;
  238. }
  239. #if !defined(CONFIG_USER_ONLY)
  240. hwaddr cpu_get_phys_page_debug(CPUMIPSState *env, target_ulong addr)
  241. {
  242. hwaddr phys_addr;
  243. int prot;
  244. if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT) != 0)
  245. return -1;
  246. return phys_addr;
  247. }
  248. #endif
  249. int cpu_mips_handle_mmu_fault (CPUMIPSState *env, target_ulong address, int rw,
  250. int mmu_idx)
  251. {
  252. #if !defined(CONFIG_USER_ONLY)
  253. hwaddr physical;
  254. int prot;
  255. int access_type;
  256. #endif
  257. int ret = 0;
  258. #if 0
  259. log_cpu_state(env, 0);
  260. #endif
  261. qemu_log("%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d mmu_idx %d\n",
  262. __func__, env->active_tc.PC, address, rw, mmu_idx);
  263. rw &= 1;
  264. /* data access */
  265. #if !defined(CONFIG_USER_ONLY)
  266. /* XXX: put correct access by using cpu_restore_state()
  267. correctly */
  268. access_type = ACCESS_INT;
  269. ret = get_physical_address(env, &physical, &prot,
  270. address, rw, access_type);
  271. qemu_log("%s address=" TARGET_FMT_lx " ret %d physical " TARGET_FMT_plx " prot %d\n",
  272. __func__, address, ret, physical, prot);
  273. if (ret == TLBRET_MATCH) {
  274. tlb_set_page(env, address & TARGET_PAGE_MASK,
  275. physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
  276. mmu_idx, TARGET_PAGE_SIZE);
  277. ret = 0;
  278. } else if (ret < 0)
  279. #endif
  280. {
  281. raise_mmu_exception(env, address, rw, ret);
  282. ret = 1;
  283. }
  284. return ret;
  285. }
  286. #if !defined(CONFIG_USER_ONLY)
  287. hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int rw)
  288. {
  289. hwaddr physical;
  290. int prot;
  291. int access_type;
  292. int ret = 0;
  293. rw &= 1;
  294. /* data access */
  295. access_type = ACCESS_INT;
  296. ret = get_physical_address(env, &physical, &prot,
  297. address, rw, access_type);
  298. if (ret != TLBRET_MATCH) {
  299. raise_mmu_exception(env, address, rw, ret);
  300. return -1LL;
  301. } else {
  302. return physical;
  303. }
  304. }
  305. #endif
  306. static const char * const excp_names[EXCP_LAST + 1] = {
  307. [EXCP_RESET] = "reset",
  308. [EXCP_SRESET] = "soft reset",
  309. [EXCP_DSS] = "debug single step",
  310. [EXCP_DINT] = "debug interrupt",
  311. [EXCP_NMI] = "non-maskable interrupt",
  312. [EXCP_MCHECK] = "machine check",
  313. [EXCP_EXT_INTERRUPT] = "interrupt",
  314. [EXCP_DFWATCH] = "deferred watchpoint",
  315. [EXCP_DIB] = "debug instruction breakpoint",
  316. [EXCP_IWATCH] = "instruction fetch watchpoint",
  317. [EXCP_AdEL] = "address error load",
  318. [EXCP_AdES] = "address error store",
  319. [EXCP_TLBF] = "TLB refill",
  320. [EXCP_IBE] = "instruction bus error",
  321. [EXCP_DBp] = "debug breakpoint",
  322. [EXCP_SYSCALL] = "syscall",
  323. [EXCP_BREAK] = "break",
  324. [EXCP_CpU] = "coprocessor unusable",
  325. [EXCP_RI] = "reserved instruction",
  326. [EXCP_OVERFLOW] = "arithmetic overflow",
  327. [EXCP_TRAP] = "trap",
  328. [EXCP_FPE] = "floating point",
  329. [EXCP_DDBS] = "debug data break store",
  330. [EXCP_DWATCH] = "data watchpoint",
  331. [EXCP_LTLBL] = "TLB modify",
  332. [EXCP_TLBL] = "TLB load",
  333. [EXCP_TLBS] = "TLB store",
  334. [EXCP_DBE] = "data bus error",
  335. [EXCP_DDBL] = "debug data break load",
  336. [EXCP_THREAD] = "thread",
  337. [EXCP_MDMX] = "MDMX",
  338. [EXCP_C2E] = "precise coprocessor 2",
  339. [EXCP_CACHE] = "cache error",
  340. };
  341. #if !defined(CONFIG_USER_ONLY)
  342. static target_ulong exception_resume_pc (CPUMIPSState *env)
  343. {
  344. target_ulong bad_pc;
  345. target_ulong isa_mode;
  346. isa_mode = !!(env->hflags & MIPS_HFLAG_M16);
  347. bad_pc = env->active_tc.PC | isa_mode;
  348. if (env->hflags & MIPS_HFLAG_BMASK) {
  349. /* If the exception was raised from a delay slot, come back to
  350. the jump. */
  351. bad_pc -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
  352. }
  353. return bad_pc;
  354. }
  355. static void set_hflags_for_handler (CPUMIPSState *env)
  356. {
  357. /* Exception handlers are entered in 32-bit mode. */
  358. env->hflags &= ~(MIPS_HFLAG_M16);
  359. /* ...except that microMIPS lets you choose. */
  360. if (env->insn_flags & ASE_MICROMIPS) {
  361. env->hflags |= (!!(env->CP0_Config3
  362. & (1 << CP0C3_ISA_ON_EXC))
  363. << MIPS_HFLAG_M16_SHIFT);
  364. }
  365. }
  366. #endif
  367. void do_interrupt (CPUMIPSState *env)
  368. {
  369. #if !defined(CONFIG_USER_ONLY)
  370. MIPSCPU *cpu = mips_env_get_cpu(env);
  371. target_ulong offset;
  372. int cause = -1;
  373. const char *name;
  374. if (qemu_log_enabled() && env->exception_index != EXCP_EXT_INTERRUPT) {
  375. if (env->exception_index < 0 || env->exception_index > EXCP_LAST)
  376. name = "unknown";
  377. else
  378. name = excp_names[env->exception_index];
  379. qemu_log("%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " %s exception\n",
  380. __func__, env->active_tc.PC, env->CP0_EPC, name);
  381. }
  382. if (env->exception_index == EXCP_EXT_INTERRUPT &&
  383. (env->hflags & MIPS_HFLAG_DM))
  384. env->exception_index = EXCP_DINT;
  385. offset = 0x180;
  386. switch (env->exception_index) {
  387. case EXCP_DSS:
  388. env->CP0_Debug |= 1 << CP0DB_DSS;
  389. /* Debug single step cannot be raised inside a delay slot and
  390. resume will always occur on the next instruction
  391. (but we assume the pc has always been updated during
  392. code translation). */
  393. env->CP0_DEPC = env->active_tc.PC | !!(env->hflags & MIPS_HFLAG_M16);
  394. goto enter_debug_mode;
  395. case EXCP_DINT:
  396. env->CP0_Debug |= 1 << CP0DB_DINT;
  397. goto set_DEPC;
  398. case EXCP_DIB:
  399. env->CP0_Debug |= 1 << CP0DB_DIB;
  400. goto set_DEPC;
  401. case EXCP_DBp:
  402. env->CP0_Debug |= 1 << CP0DB_DBp;
  403. goto set_DEPC;
  404. case EXCP_DDBS:
  405. env->CP0_Debug |= 1 << CP0DB_DDBS;
  406. goto set_DEPC;
  407. case EXCP_DDBL:
  408. env->CP0_Debug |= 1 << CP0DB_DDBL;
  409. set_DEPC:
  410. env->CP0_DEPC = exception_resume_pc(env);
  411. env->hflags &= ~MIPS_HFLAG_BMASK;
  412. enter_debug_mode:
  413. env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
  414. env->hflags &= ~(MIPS_HFLAG_KSU);
  415. /* EJTAG probe trap enable is not implemented... */
  416. if (!(env->CP0_Status & (1 << CP0St_EXL)))
  417. env->CP0_Cause &= ~(1 << CP0Ca_BD);
  418. env->active_tc.PC = (int32_t)0xBFC00480;
  419. set_hflags_for_handler(env);
  420. break;
  421. case EXCP_RESET:
  422. cpu_reset(CPU(cpu));
  423. break;
  424. case EXCP_SRESET:
  425. env->CP0_Status |= (1 << CP0St_SR);
  426. memset(env->CP0_WatchLo, 0, sizeof(*env->CP0_WatchLo));
  427. goto set_error_EPC;
  428. case EXCP_NMI:
  429. env->CP0_Status |= (1 << CP0St_NMI);
  430. set_error_EPC:
  431. env->CP0_ErrorEPC = exception_resume_pc(env);
  432. env->hflags &= ~MIPS_HFLAG_BMASK;
  433. env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
  434. env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
  435. env->hflags &= ~(MIPS_HFLAG_KSU);
  436. if (!(env->CP0_Status & (1 << CP0St_EXL)))
  437. env->CP0_Cause &= ~(1 << CP0Ca_BD);
  438. env->active_tc.PC = (int32_t)0xBFC00000;
  439. set_hflags_for_handler(env);
  440. break;
  441. case EXCP_EXT_INTERRUPT:
  442. cause = 0;
  443. if (env->CP0_Cause & (1 << CP0Ca_IV))
  444. offset = 0x200;
  445. if (env->CP0_Config3 & ((1 << CP0C3_VInt) | (1 << CP0C3_VEIC))) {
  446. /* Vectored Interrupts. */
  447. unsigned int spacing;
  448. unsigned int vector;
  449. unsigned int pending = (env->CP0_Cause & CP0Ca_IP_mask) >> 8;
  450. pending &= env->CP0_Status >> 8;
  451. /* Compute the Vector Spacing. */
  452. spacing = (env->CP0_IntCtl >> CP0IntCtl_VS) & ((1 << 6) - 1);
  453. spacing <<= 5;
  454. if (env->CP0_Config3 & (1 << CP0C3_VInt)) {
  455. /* For VInt mode, the MIPS computes the vector internally. */
  456. for (vector = 7; vector > 0; vector--) {
  457. if (pending & (1 << vector)) {
  458. /* Found it. */
  459. break;
  460. }
  461. }
  462. } else {
  463. /* For VEIC mode, the external interrupt controller feeds the
  464. vector through the CP0Cause IP lines. */
  465. vector = pending;
  466. }
  467. offset = 0x200 + vector * spacing;
  468. }
  469. goto set_EPC;
  470. case EXCP_LTLBL:
  471. cause = 1;
  472. goto set_EPC;
  473. case EXCP_TLBL:
  474. cause = 2;
  475. if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
  476. #if defined(TARGET_MIPS64)
  477. int R = env->CP0_BadVAddr >> 62;
  478. int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
  479. int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
  480. int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
  481. if (((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX)) &&
  482. (!(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F))))
  483. offset = 0x080;
  484. else
  485. #endif
  486. offset = 0x000;
  487. }
  488. goto set_EPC;
  489. case EXCP_TLBS:
  490. cause = 3;
  491. if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
  492. #if defined(TARGET_MIPS64)
  493. int R = env->CP0_BadVAddr >> 62;
  494. int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
  495. int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
  496. int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
  497. if (((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX)) &&
  498. (!(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F))))
  499. offset = 0x080;
  500. else
  501. #endif
  502. offset = 0x000;
  503. }
  504. goto set_EPC;
  505. case EXCP_AdEL:
  506. cause = 4;
  507. goto set_EPC;
  508. case EXCP_AdES:
  509. cause = 5;
  510. goto set_EPC;
  511. case EXCP_IBE:
  512. cause = 6;
  513. goto set_EPC;
  514. case EXCP_DBE:
  515. cause = 7;
  516. goto set_EPC;
  517. case EXCP_SYSCALL:
  518. cause = 8;
  519. goto set_EPC;
  520. case EXCP_BREAK:
  521. cause = 9;
  522. goto set_EPC;
  523. case EXCP_RI:
  524. cause = 10;
  525. goto set_EPC;
  526. case EXCP_CpU:
  527. cause = 11;
  528. env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) |
  529. (env->error_code << CP0Ca_CE);
  530. goto set_EPC;
  531. case EXCP_OVERFLOW:
  532. cause = 12;
  533. goto set_EPC;
  534. case EXCP_TRAP:
  535. cause = 13;
  536. goto set_EPC;
  537. case EXCP_FPE:
  538. cause = 15;
  539. goto set_EPC;
  540. case EXCP_C2E:
  541. cause = 18;
  542. goto set_EPC;
  543. case EXCP_MDMX:
  544. cause = 22;
  545. goto set_EPC;
  546. case EXCP_DWATCH:
  547. cause = 23;
  548. /* XXX: TODO: manage defered watch exceptions */
  549. goto set_EPC;
  550. case EXCP_MCHECK:
  551. cause = 24;
  552. goto set_EPC;
  553. case EXCP_THREAD:
  554. cause = 25;
  555. goto set_EPC;
  556. case EXCP_DSPDIS:
  557. cause = 26;
  558. goto set_EPC;
  559. case EXCP_CACHE:
  560. cause = 30;
  561. if (env->CP0_Status & (1 << CP0St_BEV)) {
  562. offset = 0x100;
  563. } else {
  564. offset = 0x20000100;
  565. }
  566. set_EPC:
  567. if (!(env->CP0_Status & (1 << CP0St_EXL))) {
  568. env->CP0_EPC = exception_resume_pc(env);
  569. if (env->hflags & MIPS_HFLAG_BMASK) {
  570. env->CP0_Cause |= (1 << CP0Ca_BD);
  571. } else {
  572. env->CP0_Cause &= ~(1 << CP0Ca_BD);
  573. }
  574. env->CP0_Status |= (1 << CP0St_EXL);
  575. env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
  576. env->hflags &= ~(MIPS_HFLAG_KSU);
  577. }
  578. env->hflags &= ~MIPS_HFLAG_BMASK;
  579. if (env->CP0_Status & (1 << CP0St_BEV)) {
  580. env->active_tc.PC = (int32_t)0xBFC00200;
  581. } else {
  582. env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff);
  583. }
  584. env->active_tc.PC += offset;
  585. set_hflags_for_handler(env);
  586. env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC);
  587. break;
  588. default:
  589. qemu_log("Invalid MIPS exception %d. Exiting\n", env->exception_index);
  590. printf("Invalid MIPS exception %d. Exiting\n", env->exception_index);
  591. exit(1);
  592. }
  593. if (qemu_log_enabled() && env->exception_index != EXCP_EXT_INTERRUPT) {
  594. qemu_log("%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d\n"
  595. " S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n",
  596. __func__, env->active_tc.PC, env->CP0_EPC, cause,
  597. env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr,
  598. env->CP0_DEPC);
  599. }
  600. #endif
  601. env->exception_index = EXCP_NONE;
  602. }
  603. #if !defined(CONFIG_USER_ONLY)
  604. void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra)
  605. {
  606. r4k_tlb_t *tlb;
  607. target_ulong addr;
  608. target_ulong end;
  609. uint8_t ASID = env->CP0_EntryHi & 0xFF;
  610. target_ulong mask;
  611. tlb = &env->tlb->mmu.r4k.tlb[idx];
  612. /* The qemu TLB is flushed when the ASID changes, so no need to
  613. flush these entries again. */
  614. if (tlb->G == 0 && tlb->ASID != ASID) {
  615. return;
  616. }
  617. if (use_extra && env->tlb->tlb_in_use < MIPS_TLB_MAX) {
  618. /* For tlbwr, we can shadow the discarded entry into
  619. a new (fake) TLB entry, as long as the guest can not
  620. tell that it's there. */
  621. env->tlb->mmu.r4k.tlb[env->tlb->tlb_in_use] = *tlb;
  622. env->tlb->tlb_in_use++;
  623. return;
  624. }
  625. /* 1k pages are not supported. */
  626. mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
  627. if (tlb->V0) {
  628. addr = tlb->VPN & ~mask;
  629. #if defined(TARGET_MIPS64)
  630. if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {
  631. addr |= 0x3FFFFF0000000000ULL;
  632. }
  633. #endif
  634. end = addr | (mask >> 1);
  635. while (addr < end) {
  636. tlb_flush_page (env, addr);
  637. addr += TARGET_PAGE_SIZE;
  638. }
  639. }
  640. if (tlb->V1) {
  641. addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1);
  642. #if defined(TARGET_MIPS64)
  643. if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {
  644. addr |= 0x3FFFFF0000000000ULL;
  645. }
  646. #endif
  647. end = addr | mask;
  648. while (addr - 1 < end) {
  649. tlb_flush_page (env, addr);
  650. addr += TARGET_PAGE_SIZE;
  651. }
  652. }
  653. }
  654. #endif