exception.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /*---------------------------------------------------------------------------------
  2. $Id: gurumeditation.c,v 1.6 2006/08/03 09:35:36 wntrmute Exp $
  3. Copyright (C) 2005
  4. Dave Murphy (WinterMute)
  5. This software is provided 'as-is', without any express or implied
  6. warranty. In no event will the authors be held liable for any
  7. damages arising from the use of this software.
  8. Permission is granted to anyone to use this software for any
  9. purpose, including commercial applications, and to alter it and
  10. redistribute it freely, subject to the following restrictions:
  11. 1. The origin of this software must not be misrepresented; you
  12. must not claim that you wrote the original software. If you use
  13. this software in a product, an acknowledgment in the product
  14. documentation would be appreciated but is not required.
  15. 2. Altered source versions must be plainly marked as such, and
  16. must not be misrepresented as being the original software.
  17. 3. This notice may not be removed or altered from any source
  18. distribution.
  19. $Log: gurumeditation.c,v $
  20. Revision 1.6 2006/08/03 09:35:36 wntrmute
  21. fix storing pc
  22. Revision 1.5 2006/07/06 02:14:33 wntrmute
  23. read r15 in enterException
  24. add return to bios
  25. Revision 1.4 2006/06/21 20:12:39 wntrmute
  26. thumb ldrsh has register offset
  27. Revision 1.3 2006/06/19 19:12:01 wntrmute
  28. correct prototypes again
  29. add defaultHandler function to install default handler
  30. Revision 1.2 2006/06/19 18:22:25 wntrmute
  31. completed thumb address calculations
  32. Revision 1.1 2006/06/19 14:09:37 wntrmute
  33. split default exception handler into separate file
  34. correct prototypes
  35. ---------------------------------------------------------------------------------*/
  36. // Modified by kvance 2007-09-13
  37. // Disable DMA and reset scrolling as soon as the exception handler is called.
  38. #include "exception.h"
  39. #include "../../src/config.h"
  40. #include "../../src/compat.h"
  41. #ifdef CONFIG_NDS
  42. #include <inttypes.h>
  43. #include <stdio.h>
  44. //---------------------------------------------------------------------------------
  45. static unsigned long ARMShift(unsigned long value,unsigned char shift) {
  46. //---------------------------------------------------------------------------------
  47. int index, i;
  48. bool isN;
  49. // no shift at all
  50. if (shift == 0x0B) return value ;
  51. if (shift & 0x01) {
  52. // shift index is a register
  53. index = exceptionRegisters[(shift >> 4) & 0x0F];
  54. } else {
  55. // constant shift index
  56. index = ((shift >> 3) & 0x1F) ;
  57. } ;
  58. switch (shift & 0x06) {
  59. case 0x00:
  60. // logical left
  61. return (value << index) ;
  62. case 0x02:
  63. // logical right
  64. return (value >> index) ;
  65. case 0x04:
  66. // arithmetical right
  67. isN = (value & 0x80000000) ;
  68. value = value >> index ;
  69. if (isN) {
  70. for (i=31;i>31-index;i--) {
  71. value = value | (1 << i) ;
  72. } ;
  73. } ;
  74. return value ;
  75. case 0x06:
  76. // rotate right
  77. index = index & 0x1F;
  78. value = (value >> index) | (value << (32-index));
  79. return value;
  80. };
  81. return value;
  82. }
  83. //---------------------------------------------------------------------------------
  84. static u32 getExceptionAddress( u32 opcodeAddress, u32 thumbState) {
  85. //---------------------------------------------------------------------------------
  86. int Rf, Rb, Rd, Rn, Rm;
  87. if (thumbState) {
  88. // Thumb
  89. unsigned short opcode = *(unsigned short *)opcodeAddress ;
  90. // ldr r,[pc,###] 01001ddd ffffffff
  91. // ldr r,[r,r] 0101xx0f ffbbbddd
  92. // ldrsh 0101xx1f ffbbbddd
  93. // ldr r,[r,imm] 011xxfff ffbbbddd
  94. // ldrh 1000xfff ffbbbddd
  95. // ldr r,[sp,###] 1001xddd ffffffff
  96. // push 1011x10l llllllll
  97. // ldm 1100xbbb llllllll
  98. if ((opcode & 0xF800) == 0x4800) {
  99. // ldr r,[pc,###]
  100. s8 offset = opcode & 0xff;
  101. return exceptionRegisters[15] + offset;
  102. } else if ((opcode & 0xF200) == 0x5000) {
  103. // ldr r,[r,r]
  104. Rb = (opcode >> 3) & 0x07 ;
  105. Rf = (opcode >> 6) & 0x07 ;
  106. return exceptionRegisters[Rb] + exceptionRegisters[Rf];
  107. } else if ((opcode & 0xF200) == 0x5200) {
  108. // ldrsh
  109. Rb = (opcode >> 3) & 0x07;
  110. Rf = (opcode >> 6) & 0x03;
  111. return exceptionRegisters[Rb] + exceptionRegisters[Rf];
  112. } else if ((opcode & 0xE000) == 0x6000) {
  113. // ldr r,[r,imm]
  114. Rb = (opcode >> 3) & 0x07;
  115. Rf = (opcode >> 6) & 0x1F ;
  116. return exceptionRegisters[Rb] + (Rf << 2);
  117. } else if ((opcode & 0xF000) == 0x8000) {
  118. // ldrh
  119. Rb = (opcode >> 3) & 0x07 ;
  120. Rf = (opcode >> 6) & 0x1F ;
  121. return exceptionRegisters[Rb] + (Rf << 2);
  122. } else if ((opcode & 0xF000) == 0x9000) {
  123. // ldr r,[sp,#imm]
  124. s8 offset = opcode & 0xff;
  125. return exceptionRegisters[13] + offset;
  126. } else if ((opcode & 0xF700) == 0xB500) {
  127. // push/pop
  128. return exceptionRegisters[13];
  129. } else if ((opcode & 0xF000) == 0xC000) {
  130. // ldm/stm
  131. Rd = (opcode >> 8) & 0x07;
  132. return exceptionRegisters[Rd];
  133. }
  134. } else {
  135. // arm32
  136. unsigned long opcode = *(unsigned long *)opcodeAddress ;
  137. // SWP xxxx0001 0x00nnnn dddd0000 1001mmmm
  138. // STR/LDR xxxx01xx xxxxnnnn ddddffff ffffffff
  139. // STRH/LDRH xxxx000x x0xxnnnn dddd0000 1xx1mmmm
  140. // STRH/LDRH xxxx000x x1xxnnnn ddddffff 1xx1ffff
  141. // STM/LDM xxxx100x xxxxnnnn llllllll llllllll
  142. if ((opcode & 0x0FB00FF0) == 0x01000090) {
  143. // SWP
  144. Rn = (opcode >> 16) & 0x0F;
  145. return exceptionRegisters[Rn];
  146. } else if ((opcode & 0x0C000000) == 0x04000000) {
  147. // STR/LDR
  148. Rn = (opcode >> 16) & 0x0F;
  149. if (opcode & 0x02000000) {
  150. // Register offset
  151. Rm = opcode & 0x0F;
  152. if (opcode & 0x01000000) {
  153. unsigned short shift = (unsigned short)((opcode >> 4) & 0xFF) ;
  154. // pre indexing
  155. long Offset = ARMShift(exceptionRegisters[Rm],shift);
  156. // add or sub the offset depending on the U-Bit
  157. return exceptionRegisters[Rn] + ((opcode & 0x00800000)?Offset:-Offset);
  158. } else {
  159. // post indexing
  160. return exceptionRegisters[Rn];
  161. }
  162. } else {
  163. // Immediate offset
  164. unsigned long Offset = (opcode & 0xFFF) ;
  165. if (opcode & 0x01000000) {
  166. // pre indexing
  167. // add or sub the offset depending on the U-Bit
  168. return exceptionRegisters[Rn] + ((opcode & 0x00800000)?Offset:-Offset);
  169. } else {
  170. // post indexing
  171. return exceptionRegisters[Rn];
  172. }
  173. }
  174. } else if ((opcode & 0x0E400F90) == 0x00000090) {
  175. unsigned short shift;
  176. long Offset;
  177. // LDRH/STRH with register Rm
  178. Rn = (opcode >> 16) & 0x0F;
  179. Rd = (opcode >> 12) & 0x0F;
  180. Rm = opcode & 0x0F;
  181. shift = (unsigned short)((opcode >> 4) & 0xFF);
  182. Offset = ARMShift(exceptionRegisters[Rm],shift);
  183. // add or sub the offset depending on the U-Bit
  184. return exceptionRegisters[Rn] + ((opcode & 0x00800000)?Offset:-Offset);
  185. } else if ((opcode & 0x0E400F90) == 0x00400090) {
  186. unsigned long Offset;
  187. // LDRH/STRH with immediate offset
  188. Rn = (opcode >> 16) & 0x0F;
  189. Rd = (opcode >> 12) & 0x0F;
  190. Offset = (opcode & 0xF) | ((opcode & 0xF00)>>8) ;
  191. // add or sub the offset depending on the U-Bit
  192. return exceptionRegisters[Rn] + ((opcode & 0x00800000)?Offset:-Offset) ;
  193. } else if ((opcode & 0x0E000000) == 0x08000000) {
  194. // LDM/STM
  195. Rn = (opcode >> 16) & 0x0F;
  196. return exceptionRegisters[Rn];
  197. }
  198. }
  199. return 0;
  200. }
  201. static const char *registerNames[] =
  202. { "r0","r1","r2","r3","r4","r5","r6","r7",
  203. "r8 ","r9 ","r10","r11","r12","sp ","lr ","pc " };
  204. extern const char __itcm_start[];
  205. //---------------------------------------------------------------------------------
  206. static void mzxExceptionHandler() {
  207. //---------------------------------------------------------------------------------
  208. u32 *stack, currentMode, thumbState, codeAddress, exceptionAddress = 0;
  209. int i, offset = 8;
  210. DMA0_CR = 0;
  211. DMA1_CR = 0;
  212. DMA2_CR = 0;
  213. DMA3_CR = 0;
  214. REG_BG0HOFS_SUB = 0;
  215. REG_BG0VOFS_SUB = 0;
  216. videoSetMode(0);
  217. videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);
  218. vramSetBankC(VRAM_C_SUB_BG);
  219. REG_BG0CNT_SUB = BG_MAP_BASE(31);
  220. BG_PALETTE_SUB[0] = RGB15(31,0,0);
  221. BG_PALETTE_SUB[255] = RGB15(31,31,31);
  222. consoleDemoInit();
  223. iprintf("\x1b[5CGuru Meditation Error!\n");
  224. currentMode = getCPSR() & 0x1f;
  225. thumbState = ((*(u32*)0x027FFD90) & 0x20);
  226. if ( currentMode == 0x17 ) {
  227. iprintf ("\x1b[10Cdata abort!\n\n");
  228. codeAddress = exceptionRegisters[15] - offset;
  229. if ( (codeAddress > 0x02000000 && codeAddress < 0x02400000) ||
  230. (codeAddress > (u32)__itcm_start && codeAddress < (u32)(__itcm_start + 32768)) )
  231. exceptionAddress = getExceptionAddress( codeAddress, thumbState);
  232. else
  233. exceptionAddress = codeAddress;
  234. } else {
  235. if (thumbState)
  236. offset = 2;
  237. else
  238. offset = 4;
  239. iprintf("\x1b[5Cundefined instruction!\n\n");
  240. codeAddress = exceptionRegisters[15] - offset;
  241. exceptionAddress = codeAddress;
  242. }
  243. iprintf(" pc: %08"PRIX32" addr: %08"PRIX32"\n\n",codeAddress,exceptionAddress);
  244. for ( i=0; i < 8; i++ ) {
  245. iprintf( " %s: %08"PRIX32" %s: %08"PRIX32"\n",
  246. registerNames[i], (u32)exceptionRegisters[i],
  247. registerNames[i+8], (u32)exceptionRegisters[i+8]);
  248. }
  249. iprintf("\n");
  250. stack = (u32 *)exceptionRegisters[13];
  251. for ( i=0; i<10; i++ ) {
  252. iprintf( "\x1b[%d;2H%08"PRIX32": %08"PRIX32" %08"PRIX32, i + 14, (u32)&stack[i*2],stack[i*2], stack[(i*2)+1] );
  253. }
  254. while(1);
  255. }
  256. //---------------------------------------------------------------------------------
  257. void setMzxExceptionHandler() {
  258. //---------------------------------------------------------------------------------
  259. setExceptionHandler(mzxExceptionHandler) ;
  260. }
  261. #endif // CONFIG_NDS