Guest User

Untitled

a guest
May 25th, 2018
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 66.08 KB | None | 0 0
  1. // -*- C++ -*-
  2. // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
  3. // Copyright (C) 1999-2003 Forgotten
  4. // Copyright (C) 2004 Forgotten and the VBA development team
  5.  
  6. // This program is free software; you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation; either version 2, or(at your option)
  9. // any later version.
  10. //
  11. // This program 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
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with this program; if not, write to the Free Software Foundation,
  18. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19.  
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. //#include <memory.h>
  24. #include <stdarg.h>
  25. #include <string.h>
  26.  
  27. #include "GBA.h"
  28. #include "GBAcpu.h"
  29. #include "GBAinline.h"
  30. #include "../Globals.h"
  31. #include "../EEprom.h"
  32. #include "../Flash.h"
  33. #include "../Sound.h"
  34. #include "../Sram.h"
  35. #include "../bios.h"
  36. #include "../Cheats.h"
  37. #include "../NLS.h"
  38. #include "../elf.h"
  39. #include "../Util.h"
  40. #include "../Port.h"
  41. #include "../System.h"
  42. #include "agbprint.h"
  43. #ifdef PROFILING
  44. #include "prof/prof.h"
  45. #endif
  46.  
  47. #ifdef _MSC_VER
  48. #define snprintf _snprintf
  49. #endif
  50.  
  51.  
  52. static int clockTicks;
  53.  
  54. static INSN_REGPARM void thumbUnknownInsn(u32 opcode)
  55. {
  56. #ifdef GBA_LOGGING
  57. if(systemVerbose & VERBOSE_UNDEFINED)
  58. log("Undefined THUMB instruction %04x at %08x\n", opcode, armNextPC-2);
  59. #endif
  60. CPUUndefinedException();
  61. }
  62.  
  63. #ifdef BKPT_SUPPORT
  64. static INSN_REGPARM void thumbBreakpoint(u32 opcode)
  65. {
  66. reg[15].I -= 2;
  67. armNextPC -= 2;
  68. dbgSignal(5, opcode & 255);
  69. clockTicks = -1;
  70. }
  71. #endif
  72.  
  73. // Common macros //////////////////////////////////////////////////////////
  74.  
  75. #ifdef BKPT_SUPPORT
  76. # define THUMB_CONSOLE_OUTPUT(a,b) do { \
  77. if ((opcode == 0x4000) && (reg[0].I == 0xC0DED00D)) { \
  78. dbgOutput((a), (b)); \
  79. } \
  80. } while (0)
  81. # define UPDATE_OLDREG do { \
  82. if (debugger_last) { \
  83. snprintf(oldbuffer, sizeof(oldbuffer), "%08X", \
  84. armState ? reg[15].I - 4 : reg[15].I - 2); \
  85. int i; \
  86. for (i = 0; i < 18; i++) { \
  87. oldreg[i] = reg[i].I; \
  88. } \
  89. } \
  90. } while (0)
  91. #else
  92. # define THUMB_CONSOLE_OUTPUT(a,b)
  93. # define UPDATE_OLDREG
  94. #endif
  95.  
  96. #define NEG(i) ((i) >> 31)
  97. #define POS(i) ((~(i)) >> 31)
  98.  
  99. #if 1 // Wii port override
  100. //#ifndef C_CORE
  101. #ifdef __GNUC__
  102. #ifdef __POWERPC__
  103. #define ADD_RD_RS_RN(N) \
  104. { \
  105. register int Flags; \
  106. register int Result; \
  107. asm volatile("addco. %0, %2, %3\n" \
  108. "mcrxr cr1\n" \
  109. "mfcr %1\n" \
  110. : "=r" (Result), \
  111. "=r" (Flags) \
  112. : "r" (reg[source].I), \
  113. "r" (reg[N].I) \
  114. ); \
  115. reg[dest].I = Result; \
  116. Z_FLAG = (Flags >> 29) & 1; \
  117. N_FLAG = (Flags >> 31) & 1; \
  118. C_FLAG = (Flags >> 25) & 1; \
  119. V_FLAG = (Flags >> 26) & 1; \
  120. }
  121. #define ADD_RD_RS_O3(N) \
  122. { \
  123. register int Flags; \
  124. register int Result; \
  125. asm volatile("addco. %0, %2, %3\n" \
  126. "mcrxr cr1\n" \
  127. "mfcr %1\n" \
  128. : "=r" (Result), \
  129. "=r" (Flags) \
  130. : "r" (reg[source].I), \
  131. "r" (N) \
  132. ); \
  133. reg[dest].I = Result; \
  134. Z_FLAG = (Flags >> 29) & 1; \
  135. N_FLAG = (Flags >> 31) & 1; \
  136. C_FLAG = (Flags >> 25) & 1; \
  137. V_FLAG = (Flags >> 26) & 1; \
  138. }
  139. #define ADD_RD_RS_O3_0 ADD_RD_RS_O3
  140. #define ADD_RN_O8(d) \
  141. {\
  142. register int Flags; \
  143. register int Result; \
  144. asm volatile("addco. %0, %2, %3\n" \
  145. "mcrxr cr1\n" \
  146. "mfcr %1\n" \
  147. : "=r" (Result), \
  148. "=r" (Flags) \
  149. : "r" (reg[(d)].I), \
  150. "r" (opcode & 255) \
  151. ); \
  152. reg[(d)].I = Result; \
  153. Z_FLAG = (Flags >> 29) & 1; \
  154. N_FLAG = (Flags >> 31) & 1; \
  155. C_FLAG = (Flags >> 25) & 1; \
  156. V_FLAG = (Flags >> 26) & 1; \
  157. }
  158. #define CMN_RD_RS \
  159. {\
  160. register int Flags; \
  161. register int Result; \
  162. asm volatile("addco. %0, %2, %3\n" \
  163. "mcrxr cr1\n" \
  164. "mfcr %1\n" \
  165. : "=r" (Result), \
  166. "=r" (Flags) \
  167. : "r" (reg[dest].I), \
  168. "r" (value) \
  169. ); \
  170. Z_FLAG = (Flags >> 29) & 1; \
  171. N_FLAG = (Flags >> 31) & 1; \
  172. C_FLAG = (Flags >> 25) & 1; \
  173. V_FLAG = (Flags >> 26) & 1; \
  174. }
  175. // Wii port - doesn't compile!
  176. #define ADC_RD_RS \
  177. {\
  178. register int Flags; \
  179. register int Result; \
  180. asm volatile("mtspr xer, %4\n" \
  181. "addeo. %0, %2, %3\n" \
  182. "mcrxr cr1\n" \
  183. "mfcr %1\n" \
  184. : "=r" (Result), \
  185. "=r" (Flags) \
  186. : "r" (reg[dest].I), \
  187. "r" (value), \
  188. "r" (C_FLAG << 29) \
  189. ); \
  190. reg[dest].I = Result; \
  191. Z_FLAG = (Flags >> 29) & 1; \
  192. N_FLAG = (Flags >> 31) & 1; \
  193. C_FLAG = (Flags >> 25) & 1; \
  194. V_FLAG = (Flags >> 26) & 1; \
  195. }
  196. #define SUB_RD_RS_RN(N) \
  197. {\
  198. register int Flags; \
  199. register int Result; \
  200. asm volatile("subco. %0, %2, %3\n" \
  201. "mcrxr cr1\n" \
  202. "mfcr %1\n" \
  203. : "=r" (Result), \
  204. "=r" (Flags) \
  205. : "r" (reg[source].I), \
  206. "r" (reg[N].I) \
  207. ); \
  208. reg[dest].I = Result; \
  209. Z_FLAG = (Flags >> 29) & 1; \
  210. N_FLAG = (Flags >> 31) & 1; \
  211. C_FLAG = (Flags >> 25) & 1; \
  212. V_FLAG = (Flags >> 26) & 1; \
  213. }
  214. #define SUB_RD_RS_O3(N) \
  215. {\
  216. register int Flags; \
  217. register int Result; \
  218. asm volatile("subco. %0, %2, %3\n" \
  219. "mcrxr cr1\n" \
  220. "mfcr %1\n" \
  221. : "=r" (Result), \
  222. "=r" (Flags) \
  223. : "r" (reg[source].I), \
  224. "r" (N) \
  225. ); \
  226. reg[dest].I = Result; \
  227. Z_FLAG = (Flags >> 29) & 1; \
  228. N_FLAG = (Flags >> 31) & 1; \
  229. C_FLAG = (Flags >> 25) & 1; \
  230. V_FLAG = (Flags >> 26) & 1; \
  231. }
  232. #define SUB_RD_RS_O3_0 SUB_RD_RS_O3
  233. #define SUB_RN_O8(d) \
  234. {\
  235. register int Flags; \
  236. register int Result; \
  237. asm volatile("subco. %0, %2, %3\n" \
  238. "mcrxr cr1\n" \
  239. "mfcr %1\n" \
  240. : "=r" (Result), \
  241. "=r" (Flags) \
  242. : "r" (reg[(d)].I), \
  243. "r" (opcode & 255) \
  244. ); \
  245. reg[(d)].I = Result; \
  246. Z_FLAG = (Flags >> 29) & 1; \
  247. N_FLAG = (Flags >> 31) & 1; \
  248. C_FLAG = (Flags >> 25) & 1; \
  249. V_FLAG = (Flags >> 26) & 1; \
  250. }
  251. #define CMP_RN_O8(d) \
  252. {\
  253. register int Flags; \
  254. register int Result; \
  255. asm volatile("subco. %0, %2, %3\n" \
  256. "mcrxr cr1\n" \
  257. "mfcr %1\n" \
  258. : "=r" (Result), \
  259. "=r" (Flags) \
  260. : "r" (reg[(d)].I), \
  261. "r" (opcode & 255) \
  262. ); \
  263. Z_FLAG = (Flags >> 29) & 1; \
  264. N_FLAG = (Flags >> 31) & 1; \
  265. C_FLAG = (Flags >> 25) & 1; \
  266. V_FLAG = (Flags >> 26) & 1; \
  267. }
  268. // Wii port - doesn't compile for some reason
  269. #define SBC_RD_RS \
  270. {\
  271. register int Flags; \
  272. register int Result; \
  273. asm volatile("mtspr xer, %4\n" \
  274. "subfeo. %0, %3, %2\n" \
  275. "mcrxr cr1\n" \
  276. "mfcr %1\n" \
  277. : "=r" (Result), \
  278. "=r" (Flags) \
  279. : "r" (reg[dest].I), \
  280. "r" (value), \
  281. "r" (C_FLAG << 29) \
  282. ); \
  283. reg[dest].I = Result; \
  284. Z_FLAG = (Flags >> 29) & 1; \
  285. N_FLAG = (Flags >> 31) & 1; \
  286. C_FLAG = (Flags >> 25) & 1; \
  287. V_FLAG = (Flags >> 26) & 1; \
  288. }
  289. #define NEG_RD_RS \
  290. {\
  291. register int Flags; \
  292. register int Result; \
  293. asm volatile("subfco. %0, %2, %3\n" \
  294. "mcrxr cr1\n" \
  295. "mfcr %1\n" \
  296. : "=r" (Result), \
  297. "=r" (Flags) \
  298. : "r" (reg[source].I), \
  299. "r" (0) \
  300. ); \
  301. reg[dest].I = Result; \
  302. Z_FLAG = (Flags >> 29) & 1; \
  303. N_FLAG = (Flags >> 31) & 1; \
  304. C_FLAG = (Flags >> 25) & 1; \
  305. V_FLAG = (Flags >> 26) & 1; \
  306. }
  307. #define CMP_RD_RS \
  308. {\
  309. register int Flags; \
  310. register int Result; \
  311. asm volatile("subco. %0, %2, %3\n" \
  312. "mcrxr cr1\n" \
  313. "mfcr %1\n" \
  314. : "=r" (Result), \
  315. "=r" (Flags) \
  316. : "r" (reg[dest].I), \
  317. "r" (value) \
  318. ); \
  319. Z_FLAG = (Flags >> 29) & 1; \
  320. N_FLAG = (Flags >> 31) & 1; \
  321. C_FLAG = (Flags >> 25) & 1; \
  322. V_FLAG = (Flags >> 26) & 1; \
  323. }
  324. #else
  325. #define EMIT1(op,arg) #op" "arg"; "
  326. #define EMIT2(op,src,dest) #op" "src", "dest"; "
  327. #define CONST(val) "$"#val
  328. #define ASMVAR(cvar) ASMVAR2 (__USER_LABEL_PREFIX__, cvar)
  329. #define ASMVAR2(prefix,cvar) STRING (prefix) cvar
  330. #define STRING(x) #x
  331. #define VAR(var) ASMVAR(#var)
  332. #define REGREF1(index) ASMVAR("reg("index")")
  333. #define REGREF2(index,scale) ASMVAR("reg(,"index","#scale")")
  334. #define eax "%%eax"
  335. #define ecx "%%ecx"
  336. #define edx "%%edx"
  337. #define ADD_RN_O8(d) \
  338. asm ("andl $0xFF, %%eax;"\
  339. "addl %%eax, %0;"\
  340. EMIT1(setsb, VAR(N_FLAG)) \
  341. EMIT1(setzb, VAR(Z_FLAG)) \
  342. EMIT1(setcb, VAR(C_FLAG)) \
  343. EMIT1(setob, VAR(V_FLAG)) \
  344. : "=m" (reg[(d)].I));
  345. #define CMN_RD_RS \
  346. asm ("add %0, %1;"\
  347. EMIT1(setsb, VAR(N_FLAG)) \
  348. EMIT1(setzb, VAR(Z_FLAG)) \
  349. EMIT1(setcb, VAR(C_FLAG)) \
  350. EMIT1(setob, VAR(V_FLAG)) \
  351. : \
  352. : "r" (value), "r" (reg[dest].I):"1");
  353. #define ADC_RD_RS \
  354. asm (EMIT2(bt,CONST(0),VAR(C_FLAG)) \
  355. "adc %1, %%ebx;"\
  356. EMIT1(setsb, VAR(N_FLAG)) \
  357. EMIT1(setzb, VAR(Z_FLAG)) \
  358. EMIT1(setcb, VAR(C_FLAG)) \
  359. EMIT1(setob, VAR(V_FLAG)) \
  360. : "=b" (reg[dest].I)\
  361. : "r" (value), "b" (reg[dest].I));
  362. #define SUB_RN_O8(d) \
  363. asm ("andl $0xFF, %%eax;"\
  364. "subl %%eax, %0;"\
  365. EMIT1(setsb, VAR(N_FLAG)) \
  366. EMIT1(setzb, VAR(Z_FLAG)) \
  367. EMIT1(setncb, VAR(C_FLAG)) \
  368. EMIT1(setob, VAR(V_FLAG)) \
  369. : "=m" (reg[(d)].I));
  370. #define MOV_RN_O8(d) \
  371. asm ("andl $0xFF, %%eax;"\
  372. EMIT2(movb,CONST(0),VAR(N_FLAG)) \
  373. "movl %%eax, %0;"\
  374. EMIT1(setzb, VAR(Z_FLAG)) \
  375. : "=m" (reg[(d)].I));
  376. #define CMP_RN_O8(d) \
  377. asm ("andl $0xFF, %%eax;"\
  378. "cmpl %%eax, %0;"\
  379. EMIT1(setsb, VAR(N_FLAG)) \
  380. EMIT1(setzb, VAR(Z_FLAG)) \
  381. EMIT1(setncb, VAR(C_FLAG)) \
  382. EMIT1(setob, VAR(V_FLAG)) \
  383. : \
  384. : "m" (reg[(d)].I));
  385. #define SBC_RD_RS \
  386. asm volatile (EMIT2(bt,CONST(0),VAR(C_FLAG)) \
  387. "cmc;"\
  388. "sbb %1, %%ebx;"\
  389. EMIT1(setsb, VAR(N_FLAG)) \
  390. EMIT1(setzb, VAR(Z_FLAG)) \
  391. EMIT1(setncb, VAR(C_FLAG)) \
  392. EMIT1(setob, VAR(V_FLAG)) \
  393. : "=b" (reg[dest].I)\
  394. : "r" (value), "b" (reg[dest].I) : "cc", "memory");
  395. #define LSL_RD_RS \
  396. asm ("shl %%cl, %%eax;"\
  397. EMIT1(setcb, VAR(C_FLAG)) \
  398. : "=a" (value)\
  399. : "a" (reg[dest].I), "c" (value));
  400. #define LSR_RD_RS \
  401. asm ("shr %%cl, %%eax;"\
  402. EMIT1(setcb, VAR(C_FLAG)) \
  403. : "=a" (value)\
  404. : "a" (reg[dest].I), "c" (value));
  405. #define ASR_RD_RS \
  406. asm ("sar %%cl, %%eax;"\
  407. EMIT1(setcb, VAR(C_FLAG)) \
  408. : "=a" (value)\
  409. : "a" (reg[dest].I), "c" (value));
  410. #define ROR_RD_RS \
  411. asm ("ror %%cl, %%eax;"\
  412. EMIT1(setcb, VAR(C_FLAG)) \
  413. : "=a" (value)\
  414. : "a" (reg[dest].I), "c" (value));
  415. #define NEG_RD_RS \
  416. asm ("neg %%ebx;"\
  417. EMIT1(setsb, VAR(N_FLAG)) \
  418. EMIT1(setzb, VAR(Z_FLAG)) \
  419. EMIT1(setncb, VAR(C_FLAG)) \
  420. EMIT1(setob, VAR(V_FLAG)) \
  421. : "=b" (reg[dest].I)\
  422. : "b" (reg[source].I));
  423. #define CMP_RD_RS \
  424. asm ("sub %0, %1;"\
  425. EMIT1(setsb, VAR(N_FLAG)) \
  426. EMIT1(setzb, VAR(Z_FLAG)) \
  427. EMIT1(setncb, VAR(C_FLAG)) \
  428. EMIT1(setob, VAR(V_FLAG)) \
  429. : \
  430. : "r" (value), "r" (reg[dest].I):"1");
  431. #define IMM5_INSN(OP,N) \
  432. asm("movl %%eax,%%ecx;" \
  433. "shrl $1,%%eax;" \
  434. "andl $7,%%ecx;" \
  435. "andl $0x1C,%%eax;" \
  436. EMIT2(movl, REGREF1(eax), edx) \
  437. OP \
  438. EMIT1(setsb, VAR(N_FLAG)) \
  439. EMIT1(setzb, VAR(Z_FLAG)) \
  440. EMIT2(movl, edx, REGREF2(ecx,4)) \
  441. : : "i" (N))
  442. #define IMM5_INSN_0(OP) \
  443. asm("movl %%eax,%%ecx;" \
  444. "shrl $1,%%eax;" \
  445. "andl $7,%%ecx;" \
  446. "andl $0x1C,%%eax;" \
  447. EMIT2(movl, REGREF1(eax), edx) \
  448. OP \
  449. EMIT1(setsb, VAR(N_FLAG)) \
  450. EMIT1(setzb, VAR(Z_FLAG)) \
  451. EMIT2(movl, edx, REGREF2(ecx,4)) \
  452. : : )
  453. #define IMM5_LSL \
  454. "shll %0,%%edx;"\
  455. EMIT1(setcb, VAR(C_FLAG))
  456. #define IMM5_LSL_0 \
  457. "testl %%edx,%%edx;"
  458. #define IMM5_LSR \
  459. "shrl %0,%%edx;"\
  460. EMIT1(setcb, VAR(C_FLAG))
  461. #define IMM5_LSR_0 \
  462. "testl %%edx,%%edx;"\
  463. EMIT1(setsb, VAR(C_FLAG)) \
  464. "xorl %%edx,%%edx;"
  465. #define IMM5_ASR \
  466. "sarl %0,%%edx;"\
  467. EMIT1(setcb, VAR(C_FLAG))
  468. #define IMM5_ASR_0 \
  469. "sarl $31,%%edx;"\
  470. EMIT1(setsb, VAR(C_FLAG))
  471. #define THREEARG_INSN(OP,N) \
  472. asm("movl %%eax,%%edx;" \
  473. "shrl $1,%%edx;" \
  474. "andl $0x1C,%%edx;" \
  475. "andl $7,%%eax;" \
  476. EMIT2(movl, REGREF1(edx), ecx) \
  477. OP(N) \
  478. EMIT1(setsb, VAR(N_FLAG)) \
  479. EMIT1(setzb, VAR(Z_FLAG)) \
  480. EMIT2(movl, ecx, REGREF2(eax,4)) \
  481. : : )
  482. #define ADD_RD_RS_RN(N) \
  483. EMIT2(add,VAR(reg)"+"#N"*4",ecx) \
  484. EMIT1(setcb, VAR(C_FLAG)) \
  485. EMIT1(setob, VAR(V_FLAG))
  486. #define ADD_RD_RS_O3(N) \
  487. "add $"#N",%%ecx;" \
  488. EMIT1(setcb, VAR(C_FLAG)) \
  489. EMIT1(setob, VAR(V_FLAG))
  490. #define ADD_RD_RS_O3_0(N) \
  491. EMIT2(movb,CONST(0),VAR(C_FLAG)) \
  492. "add $0,%%ecx;" \
  493. EMIT2(movb,CONST(0),VAR(V_FLAG))
  494. #define SUB_RD_RS_RN(N) \
  495. EMIT2(sub,VAR(reg)"+"#N"*4",ecx) \
  496. EMIT1(setncb, VAR(C_FLAG)) \
  497. EMIT1(setob, VAR(V_FLAG))
  498. #define SUB_RD_RS_O3(N) \
  499. "sub $"#N",%%ecx;" \
  500. EMIT1(setncb, VAR(C_FLAG)) \
  501. EMIT1(setob, VAR(V_FLAG))
  502. #define SUB_RD_RS_O3_0(N) \
  503. EMIT2(movb,CONST(1),VAR(C_FLAG)) \
  504. "sub $0,%%ecx;" \
  505. EMIT2(movb,CONST(0),VAR(V_FLAG))
  506. #endif
  507. #else // !__GNUC__
  508. #define ADD_RD_RS_RN(N) \
  509. {\
  510. __asm mov eax, source\
  511. __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
  512. __asm add ebx, dword ptr [OFFSET reg+4*N]\
  513. __asm mov eax, dest\
  514. __asm mov dword ptr [OFFSET reg+4*eax], ebx\
  515. __asm sets byte ptr N_FLAG\
  516. __asm setz byte ptr Z_FLAG\
  517. __asm setc byte ptr C_FLAG\
  518. __asm seto byte ptr V_FLAG\
  519. }
  520. #define ADD_RD_RS_O3(N) \
  521. {\
  522. __asm mov eax, source\
  523. __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
  524. __asm add ebx, N\
  525. __asm mov eax, dest\
  526. __asm mov dword ptr [OFFSET reg+4*eax], ebx\
  527. __asm sets byte ptr N_FLAG\
  528. __asm setz byte ptr Z_FLAG\
  529. __asm setc byte ptr C_FLAG\
  530. __asm seto byte ptr V_FLAG\
  531. }
  532. #define ADD_RD_RS_O3_0 \
  533. {\
  534. __asm mov eax, source\
  535. __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
  536. __asm add ebx, 0\
  537. __asm mov eax, dest\
  538. __asm mov dword ptr [OFFSET reg+4*eax], ebx\
  539. __asm sets byte ptr N_FLAG\
  540. __asm setz byte ptr Z_FLAG\
  541. __asm mov byte ptr C_FLAG, 0\
  542. __asm mov byte ptr V_FLAG, 0\
  543. }
  544. #define ADD_RN_O8(d) \
  545. {\
  546. __asm mov ebx, opcode\
  547. __asm and ebx, 255\
  548. __asm add dword ptr [OFFSET reg+4*(d)], ebx\
  549. __asm sets byte ptr N_FLAG\
  550. __asm setz byte ptr Z_FLAG\
  551. __asm setc byte ptr C_FLAG\
  552. __asm seto byte ptr V_FLAG\
  553. }
  554. #define CMN_RD_RS \
  555. {\
  556. __asm mov eax, dest\
  557. __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
  558. __asm add ebx, value\
  559. __asm sets byte ptr N_FLAG\
  560. __asm setz byte ptr Z_FLAG\
  561. __asm setc byte ptr C_FLAG\
  562. __asm seto byte ptr V_FLAG\
  563. }
  564. #define ADC_RD_RS \
  565. {\
  566. __asm mov ebx, dest\
  567. __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
  568. __asm bt word ptr C_FLAG, 0\
  569. __asm adc ebx, value\
  570. __asm mov eax, dest\
  571. __asm mov dword ptr [OFFSET reg+4*eax], ebx\
  572. __asm sets byte ptr N_FLAG\
  573. __asm setz byte ptr Z_FLAG\
  574. __asm setc byte ptr C_FLAG\
  575. __asm seto byte ptr V_FLAG\
  576. }
  577. #define SUB_RD_RS_RN(N) \
  578. {\
  579. __asm mov eax, source\
  580. __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
  581. __asm sub ebx, dword ptr [OFFSET reg+4*N]\
  582. __asm mov eax, dest\
  583. __asm mov dword ptr [OFFSET reg+4*eax], ebx\
  584. __asm sets byte ptr N_FLAG\
  585. __asm setz byte ptr Z_FLAG\
  586. __asm setnc byte ptr C_FLAG\
  587. __asm seto byte ptr V_FLAG\
  588. }
  589. #define SUB_RD_RS_O3(N) \
  590. {\
  591. __asm mov eax, source\
  592. __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
  593. __asm sub ebx, N\
  594. __asm mov eax, dest\
  595. __asm mov dword ptr [OFFSET reg+4*eax], ebx\
  596. __asm sets byte ptr N_FLAG\
  597. __asm setz byte ptr Z_FLAG\
  598. __asm setnc byte ptr C_FLAG\
  599. __asm seto byte ptr V_FLAG\
  600. }
  601. #define SUB_RD_RS_O3_0 \
  602. {\
  603. __asm mov eax, source\
  604. __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
  605. __asm sub ebx, 0\
  606. __asm mov eax, dest\
  607. __asm mov dword ptr [OFFSET reg+4*eax], ebx\
  608. __asm sets byte ptr N_FLAG\
  609. __asm setz byte ptr Z_FLAG\
  610. __asm mov byte ptr C_FLAG, 1\
  611. __asm mov byte ptr V_FLAG, 0\
  612. }
  613. #define SUB_RN_O8(d) \
  614. {\
  615. __asm mov ebx, opcode\
  616. __asm and ebx, 255\
  617. __asm sub dword ptr [OFFSET reg + 4*(d)], ebx\
  618. __asm sets byte ptr N_FLAG\
  619. __asm setz byte ptr Z_FLAG\
  620. __asm setnc byte ptr C_FLAG\
  621. __asm seto byte ptr V_FLAG\
  622. }
  623. #define MOV_RN_O8(d) \
  624. {\
  625. __asm mov eax, opcode\
  626. __asm and eax, 255\
  627. __asm mov dword ptr [OFFSET reg+4*(d)], eax\
  628. __asm sets byte ptr N_FLAG\
  629. __asm setz byte ptr Z_FLAG\
  630. }
  631. #define CMP_RN_O8(d) \
  632. {\
  633. __asm mov eax, dword ptr [OFFSET reg+4*(d)]\
  634. __asm mov ebx, opcode\
  635. __asm and ebx, 255\
  636. __asm sub eax, ebx\
  637. __asm sets byte ptr N_FLAG\
  638. __asm setz byte ptr Z_FLAG\
  639. __asm setnc byte ptr C_FLAG\
  640. __asm seto byte ptr V_FLAG\
  641. }
  642. #define SBC_RD_RS \
  643. {\
  644. __asm mov ebx, dest\
  645. __asm mov ebx, dword ptr [OFFSET reg + 4*ebx]\
  646. __asm mov eax, value\
  647. __asm bt word ptr C_FLAG, 0\
  648. __asm cmc\
  649. __asm sbb ebx, eax\
  650. __asm mov eax, dest\
  651. __asm mov dword ptr [OFFSET reg + 4*eax], ebx\
  652. __asm sets byte ptr N_FLAG\
  653. __asm setz byte ptr Z_FLAG\
  654. __asm setnc byte ptr C_FLAG\
  655. __asm seto byte ptr V_FLAG\
  656. }
  657. #define LSL_RD_RM_I5 \
  658. {\
  659. __asm mov eax, source\
  660. __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
  661. __asm mov cl, byte ptr shift\
  662. __asm shl eax, cl\
  663. __asm mov value, eax\
  664. __asm setc byte ptr C_FLAG\
  665. }
  666. #define LSL_RD_RS \
  667. {\
  668. __asm mov eax, dest\
  669. __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
  670. __asm mov cl, byte ptr value\
  671. __asm shl eax, cl\
  672. __asm mov value, eax\
  673. __asm setc byte ptr C_FLAG\
  674. }
  675. #define LSR_RD_RM_I5 \
  676. {\
  677. __asm mov eax, source\
  678. __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
  679. __asm mov cl, byte ptr shift\
  680. __asm shr eax, cl\
  681. __asm mov value, eax\
  682. __asm setc byte ptr C_FLAG\
  683. }
  684. #define LSR_RD_RS \
  685. {\
  686. __asm mov eax, dest\
  687. __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
  688. __asm mov cl, byte ptr value\
  689. __asm shr eax, cl\
  690. __asm mov value, eax\
  691. __asm setc byte ptr C_FLAG\
  692. }
  693. #define ASR_RD_RM_I5 \
  694. {\
  695. __asm mov eax, source\
  696. __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
  697. __asm mov cl, byte ptr shift\
  698. __asm sar eax, cl\
  699. __asm mov value, eax\
  700. __asm setc byte ptr C_FLAG\
  701. }
  702. #define ASR_RD_RS \
  703. {\
  704. __asm mov eax, dest\
  705. __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
  706. __asm mov cl, byte ptr value\
  707. __asm sar eax, cl\
  708. __asm mov value, eax\
  709. __asm setc byte ptr C_FLAG\
  710. }
  711. #define ROR_RD_RS \
  712. {\
  713. __asm mov eax, dest\
  714. __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
  715. __asm mov cl, byte ptr value\
  716. __asm ror eax, cl\
  717. __asm mov value, eax\
  718. __asm setc byte ptr C_FLAG\
  719. }
  720. #define NEG_RD_RS \
  721. {\
  722. __asm mov ebx, source\
  723. __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
  724. __asm neg ebx\
  725. __asm mov eax, dest\
  726. __asm mov dword ptr [OFFSET reg+4*eax],ebx\
  727. __asm sets byte ptr N_FLAG\
  728. __asm setz byte ptr Z_FLAG\
  729. __asm setnc byte ptr C_FLAG\
  730. __asm seto byte ptr V_FLAG\
  731. }
  732. #define CMP_RD_RS \
  733. {\
  734. __asm mov eax, dest\
  735. __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
  736. __asm sub ebx, value\
  737. __asm sets byte ptr N_FLAG\
  738. __asm setz byte ptr Z_FLAG\
  739. __asm setnc byte ptr C_FLAG\
  740. __asm seto byte ptr V_FLAG\
  741. }
  742. #endif
  743. #endif
  744.  
  745. // C core
  746. #ifndef ADDCARRY
  747. #define ADDCARRY(a, b, c) \
  748. C_FLAG = ((NEG(a) & NEG(b)) |\
  749. (NEG(a) & POS(c)) |\
  750. (NEG(b) & POS(c))) ? true : false;
  751. #endif
  752. #ifndef ADDOVERFLOW
  753. #define ADDOVERFLOW(a, b, c) \
  754. V_FLAG = ((NEG(a) & NEG(b) & POS(c)) |\
  755. (POS(a) & POS(b) & NEG(c))) ? true : false;
  756. #endif
  757. #ifndef SUBCARRY
  758. #define SUBCARRY(a, b, c) \
  759. C_FLAG = ((NEG(a) & POS(b)) |\
  760. (NEG(a) & POS(c)) |\
  761. (POS(b) & POS(c))) ? true : false;
  762. #endif
  763. #ifndef SUBOVERFLOW
  764. #define SUBOVERFLOW(a, b, c)\
  765. V_FLAG = ((NEG(a) & POS(b) & POS(c)) |\
  766. (POS(a) & NEG(b) & NEG(c))) ? true : false;
  767. #endif
  768. #ifndef ADD_RD_RS_RN
  769. #define ADD_RD_RS_RN(N) \
  770. {\
  771. u32 lhs = reg[source].I;\
  772. u32 rhs = reg[N].I;\
  773. u32 res = lhs + rhs;\
  774. reg[dest].I = res;\
  775. Z_FLAG = (res == 0) ? true : false;\
  776. N_FLAG = NEG(res) ? true : false;\
  777. ADDCARRY(lhs, rhs, res);\
  778. ADDOVERFLOW(lhs, rhs, res);\
  779. }
  780. #endif
  781. #ifndef ADD_RD_RS_O3
  782. #define ADD_RD_RS_O3(N) \
  783. {\
  784. u32 lhs = reg[source].I;\
  785. u32 rhs = N;\
  786. u32 res = lhs + rhs;\
  787. reg[dest].I = res;\
  788. Z_FLAG = (res == 0) ? true : false;\
  789. N_FLAG = NEG(res) ? true : false;\
  790. ADDCARRY(lhs, rhs, res);\
  791. ADDOVERFLOW(lhs, rhs, res);\
  792. }
  793. #endif
  794. #ifndef ADD_RD_RS_O3_0
  795. # define ADD_RD_RS_O3_0 ADD_RD_RS_O3
  796. #endif
  797. #ifndef ADD_RN_O8
  798. #define ADD_RN_O8(d) \
  799. {\
  800. u32 lhs = reg[(d)].I;\
  801. u32 rhs = (opcode & 255);\
  802. u32 res = lhs + rhs;\
  803. reg[(d)].I = res;\
  804. Z_FLAG = (res == 0) ? true : false;\
  805. N_FLAG = NEG(res) ? true : false;\
  806. ADDCARRY(lhs, rhs, res);\
  807. ADDOVERFLOW(lhs, rhs, res);\
  808. }
  809. #endif
  810. #ifndef CMN_RD_RS
  811. #define CMN_RD_RS \
  812. {\
  813. u32 lhs = reg[dest].I;\
  814. u32 rhs = value;\
  815. u32 res = lhs + rhs;\
  816. Z_FLAG = (res == 0) ? true : false;\
  817. N_FLAG = NEG(res) ? true : false;\
  818. ADDCARRY(lhs, rhs, res);\
  819. ADDOVERFLOW(lhs, rhs, res);\
  820. }
  821. #endif
  822. #ifndef ADC_RD_RS
  823. #define ADC_RD_RS \
  824. {\
  825. u32 lhs = reg[dest].I;\
  826. u32 rhs = value;\
  827. u32 res = lhs + rhs + (u32)C_FLAG;\
  828. reg[dest].I = res;\
  829. Z_FLAG = (res == 0) ? true : false;\
  830. N_FLAG = NEG(res) ? true : false;\
  831. ADDCARRY(lhs, rhs, res);\
  832. ADDOVERFLOW(lhs, rhs, res);\
  833. }
  834. #endif
  835. #ifndef SUB_RD_RS_RN
  836. #define SUB_RD_RS_RN(N) \
  837. {\
  838. u32 lhs = reg[source].I;\
  839. u32 rhs = reg[N].I;\
  840. u32 res = lhs - rhs;\
  841. reg[dest].I = res;\
  842. Z_FLAG = (res == 0) ? true : false;\
  843. N_FLAG = NEG(res) ? true : false;\
  844. SUBCARRY(lhs, rhs, res);\
  845. SUBOVERFLOW(lhs, rhs, res);\
  846. }
  847. #endif
  848. #ifndef SUB_RD_RS_O3
  849. #define SUB_RD_RS_O3(N) \
  850. {\
  851. u32 lhs = reg[source].I;\
  852. u32 rhs = N;\
  853. u32 res = lhs - rhs;\
  854. reg[dest].I = res;\
  855. Z_FLAG = (res == 0) ? true : false;\
  856. N_FLAG = NEG(res) ? true : false;\
  857. SUBCARRY(lhs, rhs, res);\
  858. SUBOVERFLOW(lhs, rhs, res);\
  859. }
  860. #endif
  861. #ifndef SUB_RD_RS_O3_0
  862. # define SUB_RD_RS_O3_0 SUB_RD_RS_O3
  863. #endif
  864. #ifndef SUB_RN_O8
  865. #define SUB_RN_O8(d) \
  866. {\
  867. u32 lhs = reg[(d)].I;\
  868. u32 rhs = (opcode & 255);\
  869. u32 res = lhs - rhs;\
  870. reg[(d)].I = res;\
  871. Z_FLAG = (res == 0) ? true : false;\
  872. N_FLAG = NEG(res) ? true : false;\
  873. SUBCARRY(lhs, rhs, res);\
  874. SUBOVERFLOW(lhs, rhs, res);\
  875. }
  876. #endif
  877. #ifndef MOV_RN_O8
  878. #define MOV_RN_O8(d) \
  879. {\
  880. reg[d].I = opcode & 255;\
  881. N_FLAG = false;\
  882. Z_FLAG = (reg[d].I ? false : true);\
  883. }
  884. #endif
  885. #ifndef CMP_RN_O8
  886. #define CMP_RN_O8(d) \
  887. {\
  888. u32 lhs = reg[(d)].I;\
  889. u32 rhs = (opcode & 255);\
  890. u32 res = lhs - rhs;\
  891. Z_FLAG = (res == 0) ? true : false;\
  892. N_FLAG = NEG(res) ? true : false;\
  893. SUBCARRY(lhs, rhs, res);\
  894. SUBOVERFLOW(lhs, rhs, res);\
  895. }
  896. #endif
  897. #ifndef SBC_RD_RS
  898. #define SBC_RD_RS \
  899. {\
  900. u32 lhs = reg[dest].I;\
  901. u32 rhs = value;\
  902. u32 res = lhs - rhs - !((u32)C_FLAG);\
  903. reg[dest].I = res;\
  904. Z_FLAG = (res == 0) ? true : false;\
  905. N_FLAG = NEG(res) ? true : false;\
  906. SUBCARRY(lhs, rhs, res);\
  907. SUBOVERFLOW(lhs, rhs, res);\
  908. }
  909. #endif
  910. #ifndef LSL_RD_RM_I5
  911. #define LSL_RD_RM_I5 \
  912. {\
  913. C_FLAG = (reg[source].I >> (32 - shift)) & 1 ? true : false;\
  914. value = reg[source].I << shift;\
  915. }
  916. #endif
  917. #ifndef LSL_RD_RS
  918. #define LSL_RD_RS \
  919. {\
  920. C_FLAG = (reg[dest].I >> (32 - value)) & 1 ? true : false;\
  921. value = reg[dest].I << value;\
  922. }
  923. #endif
  924. #ifndef LSR_RD_RM_I5
  925. #define LSR_RD_RM_I5 \
  926. {\
  927. C_FLAG = (reg[source].I >> (shift - 1)) & 1 ? true : false;\
  928. value = reg[source].I >> shift;\
  929. }
  930. #endif
  931. #ifndef LSR_RD_RS
  932. #define LSR_RD_RS \
  933. {\
  934. C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false;\
  935. value = reg[dest].I >> value;\
  936. }
  937. #endif
  938. #ifndef ASR_RD_RM_I5
  939. #define ASR_RD_RM_I5 \
  940. {\
  941. C_FLAG = ((s32)reg[source].I >> (int)(shift - 1)) & 1 ? true : false;\
  942. value = (s32)reg[source].I >> (int)shift;\
  943. }
  944. #endif
  945. #ifndef ASR_RD_RS
  946. #define ASR_RD_RS \
  947. {\
  948. C_FLAG = ((s32)reg[dest].I >> (int)(value - 1)) & 1 ? true : false;\
  949. value = (s32)reg[dest].I >> (int)value;\
  950. }
  951. #endif
  952. #ifndef ROR_RD_RS
  953. #define ROR_RD_RS \
  954. {\
  955. C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false;\
  956. value = ((reg[dest].I << (32 - value)) |\
  957. (reg[dest].I >> value));\
  958. }
  959. #endif
  960. #ifndef NEG_RD_RS
  961. #define NEG_RD_RS \
  962. {\
  963. u32 lhs = reg[source].I;\
  964. u32 rhs = 0;\
  965. u32 res = rhs - lhs;\
  966. reg[dest].I = res;\
  967. Z_FLAG = (res == 0) ? true : false;\
  968. N_FLAG = NEG(res) ? true : false;\
  969. SUBCARRY(rhs, lhs, res);\
  970. SUBOVERFLOW(rhs, lhs, res);\
  971. }
  972. #endif
  973. #ifndef CMP_RD_RS
  974. #define CMP_RD_RS \
  975. {\
  976. u32 lhs = reg[dest].I;\
  977. u32 rhs = value;\
  978. u32 res = lhs - rhs;\
  979. Z_FLAG = (res == 0) ? true : false;\
  980. N_FLAG = NEG(res) ? true : false;\
  981. SUBCARRY(lhs, rhs, res);\
  982. SUBOVERFLOW(lhs, rhs, res);\
  983. }
  984. #endif
  985. #ifndef IMM5_INSN
  986. #define IMM5_INSN(OP,N) \
  987. int dest = opcode & 0x07;\
  988. int source = (opcode >> 3) & 0x07;\
  989. u32 value;\
  990. OP(N);\
  991. reg[dest].I = value;\
  992. N_FLAG = (value & 0x80000000 ? true : false);\
  993. Z_FLAG = (value ? false : true);
  994. #define IMM5_INSN_0(OP) \
  995. int dest = opcode & 0x07;\
  996. int source = (opcode >> 3) & 0x07;\
  997. u32 value;\
  998. OP;\
  999. reg[dest].I = value;\
  1000. N_FLAG = (value & 0x80000000 ? true : false);\
  1001. Z_FLAG = (value ? false : true);
  1002. #define IMM5_LSL(N) \
  1003. int shift = N;\
  1004. LSL_RD_RM_I5;
  1005. #define IMM5_LSL_0 \
  1006. value = reg[source].I;
  1007. #define IMM5_LSR(N) \
  1008. int shift = N;\
  1009. LSR_RD_RM_I5;
  1010. #define IMM5_LSR_0 \
  1011. C_FLAG = reg[source].I & 0x80000000 ? true : false;\
  1012. value = 0;
  1013. #define IMM5_ASR(N) \
  1014. int shift = N;\
  1015. ASR_RD_RM_I5;
  1016. #define IMM5_ASR_0 \
  1017. if(reg[source].I & 0x80000000) {\
  1018. value = 0xFFFFFFFF;\
  1019. C_FLAG = true;\
  1020. } else {\
  1021. value = 0;\
  1022. C_FLAG = false;\
  1023. }
  1024. #endif
  1025. #ifndef THREEARG_INSN
  1026. #define THREEARG_INSN(OP,N) \
  1027. int dest = opcode & 0x07; \
  1028. int source = (opcode >> 3) & 0x07; \
  1029. OP(N);
  1030. #endif
  1031.  
  1032. // Shift instructions /////////////////////////////////////////////////////
  1033.  
  1034. #define DEFINE_IMM5_INSN(OP,BASE) \
  1035. static INSN_REGPARM void thumb##BASE##_00(u32 opcode) { IMM5_INSN_0(OP##_0); } \
  1036. static INSN_REGPARM void thumb##BASE##_01(u32 opcode) { IMM5_INSN(OP, 1); } \
  1037. static INSN_REGPARM void thumb##BASE##_02(u32 opcode) { IMM5_INSN(OP, 2); } \
  1038. static INSN_REGPARM void thumb##BASE##_03(u32 opcode) { IMM5_INSN(OP, 3); } \
  1039. static INSN_REGPARM void thumb##BASE##_04(u32 opcode) { IMM5_INSN(OP, 4); } \
  1040. static INSN_REGPARM void thumb##BASE##_05(u32 opcode) { IMM5_INSN(OP, 5); } \
  1041. static INSN_REGPARM void thumb##BASE##_06(u32 opcode) { IMM5_INSN(OP, 6); } \
  1042. static INSN_REGPARM void thumb##BASE##_07(u32 opcode) { IMM5_INSN(OP, 7); } \
  1043. static INSN_REGPARM void thumb##BASE##_08(u32 opcode) { IMM5_INSN(OP, 8); } \
  1044. static INSN_REGPARM void thumb##BASE##_09(u32 opcode) { IMM5_INSN(OP, 9); } \
  1045. static INSN_REGPARM void thumb##BASE##_0A(u32 opcode) { IMM5_INSN(OP,10); } \
  1046. static INSN_REGPARM void thumb##BASE##_0B(u32 opcode) { IMM5_INSN(OP,11); } \
  1047. static INSN_REGPARM void thumb##BASE##_0C(u32 opcode) { IMM5_INSN(OP,12); } \
  1048. static INSN_REGPARM void thumb##BASE##_0D(u32 opcode) { IMM5_INSN(OP,13); } \
  1049. static INSN_REGPARM void thumb##BASE##_0E(u32 opcode) { IMM5_INSN(OP,14); } \
  1050. static INSN_REGPARM void thumb##BASE##_0F(u32 opcode) { IMM5_INSN(OP,15); } \
  1051. static INSN_REGPARM void thumb##BASE##_10(u32 opcode) { IMM5_INSN(OP,16); } \
  1052. static INSN_REGPARM void thumb##BASE##_11(u32 opcode) { IMM5_INSN(OP,17); } \
  1053. static INSN_REGPARM void thumb##BASE##_12(u32 opcode) { IMM5_INSN(OP,18); } \
  1054. static INSN_REGPARM void thumb##BASE##_13(u32 opcode) { IMM5_INSN(OP,19); } \
  1055. static INSN_REGPARM void thumb##BASE##_14(u32 opcode) { IMM5_INSN(OP,20); } \
  1056. static INSN_REGPARM void thumb##BASE##_15(u32 opcode) { IMM5_INSN(OP,21); } \
  1057. static INSN_REGPARM void thumb##BASE##_16(u32 opcode) { IMM5_INSN(OP,22); } \
  1058. static INSN_REGPARM void thumb##BASE##_17(u32 opcode) { IMM5_INSN(OP,23); } \
  1059. static INSN_REGPARM void thumb##BASE##_18(u32 opcode) { IMM5_INSN(OP,24); } \
  1060. static INSN_REGPARM void thumb##BASE##_19(u32 opcode) { IMM5_INSN(OP,25); } \
  1061. static INSN_REGPARM void thumb##BASE##_1A(u32 opcode) { IMM5_INSN(OP,26); } \
  1062. static INSN_REGPARM void thumb##BASE##_1B(u32 opcode) { IMM5_INSN(OP,27); } \
  1063. static INSN_REGPARM void thumb##BASE##_1C(u32 opcode) { IMM5_INSN(OP,28); } \
  1064. static INSN_REGPARM void thumb##BASE##_1D(u32 opcode) { IMM5_INSN(OP,29); } \
  1065. static INSN_REGPARM void thumb##BASE##_1E(u32 opcode) { IMM5_INSN(OP,30); } \
  1066. static INSN_REGPARM void thumb##BASE##_1F(u32 opcode) { IMM5_INSN(OP,31); }
  1067.  
  1068. // LSL Rd, Rm, #Imm 5
  1069. DEFINE_IMM5_INSN(IMM5_LSL,00)
  1070. // LSR Rd, Rm, #Imm 5
  1071. DEFINE_IMM5_INSN(IMM5_LSR,08)
  1072. // ASR Rd, Rm, #Imm 5
  1073. DEFINE_IMM5_INSN(IMM5_ASR,10)
  1074.  
  1075. // 3-argument ADD/SUB /////////////////////////////////////////////////////
  1076.  
  1077. #define DEFINE_REG3_INSN(OP,BASE) \
  1078. static INSN_REGPARM void thumb##BASE##_0(u32 opcode) { THREEARG_INSN(OP,0); } \
  1079. static INSN_REGPARM void thumb##BASE##_1(u32 opcode) { THREEARG_INSN(OP,1); } \
  1080. static INSN_REGPARM void thumb##BASE##_2(u32 opcode) { THREEARG_INSN(OP,2); } \
  1081. static INSN_REGPARM void thumb##BASE##_3(u32 opcode) { THREEARG_INSN(OP,3); } \
  1082. static INSN_REGPARM void thumb##BASE##_4(u32 opcode) { THREEARG_INSN(OP,4); } \
  1083. static INSN_REGPARM void thumb##BASE##_5(u32 opcode) { THREEARG_INSN(OP,5); } \
  1084. static INSN_REGPARM void thumb##BASE##_6(u32 opcode) { THREEARG_INSN(OP,6); } \
  1085. static INSN_REGPARM void thumb##BASE##_7(u32 opcode) { THREEARG_INSN(OP,7); }
  1086.  
  1087. #define DEFINE_IMM3_INSN(OP,BASE) \
  1088. static INSN_REGPARM void thumb##BASE##_0(u32 opcode) { THREEARG_INSN(OP##_0,0); } \
  1089. static INSN_REGPARM void thumb##BASE##_1(u32 opcode) { THREEARG_INSN(OP,1); } \
  1090. static INSN_REGPARM void thumb##BASE##_2(u32 opcode) { THREEARG_INSN(OP,2); } \
  1091. static INSN_REGPARM void thumb##BASE##_3(u32 opcode) { THREEARG_INSN(OP,3); } \
  1092. static INSN_REGPARM void thumb##BASE##_4(u32 opcode) { THREEARG_INSN(OP,4); } \
  1093. static INSN_REGPARM void thumb##BASE##_5(u32 opcode) { THREEARG_INSN(OP,5); } \
  1094. static INSN_REGPARM void thumb##BASE##_6(u32 opcode) { THREEARG_INSN(OP,6); } \
  1095. static INSN_REGPARM void thumb##BASE##_7(u32 opcode) { THREEARG_INSN(OP,7); }
  1096.  
  1097. // ADD Rd, Rs, Rn
  1098. DEFINE_REG3_INSN(ADD_RD_RS_RN,18)
  1099. // SUB Rd, Rs, Rn
  1100. DEFINE_REG3_INSN(SUB_RD_RS_RN,1A)
  1101. // ADD Rd, Rs, #Offset3
  1102. DEFINE_IMM3_INSN(ADD_RD_RS_O3,1C)
  1103. // SUB Rd, Rs, #Offset3
  1104. DEFINE_IMM3_INSN(SUB_RD_RS_O3,1E)
  1105.  
  1106. // MOV/CMP/ADD/SUB immediate //////////////////////////////////////////////
  1107.  
  1108. // MOV R0, #Offset8
  1109. static INSN_REGPARM void thumb20(u32 opcode) { MOV_RN_O8(0); }
  1110. // MOV R1, #Offset8
  1111. static INSN_REGPARM void thumb21(u32 opcode) { MOV_RN_O8(1); }
  1112. // MOV R2, #Offset8
  1113. static INSN_REGPARM void thumb22(u32 opcode) { MOV_RN_O8(2); }
  1114. // MOV R3, #Offset8
  1115. static INSN_REGPARM void thumb23(u32 opcode) { MOV_RN_O8(3); }
  1116. // MOV R4, #Offset8
  1117. static INSN_REGPARM void thumb24(u32 opcode) { MOV_RN_O8(4); }
  1118. // MOV R5, #Offset8
  1119. static INSN_REGPARM void thumb25(u32 opcode) { MOV_RN_O8(5); }
  1120. // MOV R6, #Offset8
  1121. static INSN_REGPARM void thumb26(u32 opcode) { MOV_RN_O8(6); }
  1122. // MOV R7, #Offset8
  1123. static INSN_REGPARM void thumb27(u32 opcode) { MOV_RN_O8(7); }
  1124.  
  1125. // CMP R0, #Offset8
  1126. static INSN_REGPARM void thumb28(u32 opcode) { CMP_RN_O8(0); }
  1127. // CMP R1, #Offset8
  1128. static INSN_REGPARM void thumb29(u32 opcode) { CMP_RN_O8(1); }
  1129. // CMP R2, #Offset8
  1130. static INSN_REGPARM void thumb2A(u32 opcode) { CMP_RN_O8(2); }
  1131. // CMP R3, #Offset8
  1132. static INSN_REGPARM void thumb2B(u32 opcode) { CMP_RN_O8(3); }
  1133. // CMP R4, #Offset8
  1134. static INSN_REGPARM void thumb2C(u32 opcode) { CMP_RN_O8(4); }
  1135. // CMP R5, #Offset8
  1136. static INSN_REGPARM void thumb2D(u32 opcode) { CMP_RN_O8(5); }
  1137. // CMP R6, #Offset8
  1138. static INSN_REGPARM void thumb2E(u32 opcode) { CMP_RN_O8(6); }
  1139. // CMP R7, #Offset8
  1140. static INSN_REGPARM void thumb2F(u32 opcode) { CMP_RN_O8(7); }
  1141.  
  1142. // ADD R0,#Offset8
  1143. static INSN_REGPARM void thumb30(u32 opcode) { ADD_RN_O8(0); }
  1144. // ADD R1,#Offset8
  1145. static INSN_REGPARM void thumb31(u32 opcode) { ADD_RN_O8(1); }
  1146. // ADD R2,#Offset8
  1147. static INSN_REGPARM void thumb32(u32 opcode) { ADD_RN_O8(2); }
  1148. // ADD R3,#Offset8
  1149. static INSN_REGPARM void thumb33(u32 opcode) { ADD_RN_O8(3); }
  1150. // ADD R4,#Offset8
  1151. static INSN_REGPARM void thumb34(u32 opcode) { ADD_RN_O8(4); }
  1152. // ADD R5,#Offset8
  1153. static INSN_REGPARM void thumb35(u32 opcode) { ADD_RN_O8(5); }
  1154. // ADD R6,#Offset8
  1155. static INSN_REGPARM void thumb36(u32 opcode) { ADD_RN_O8(6); }
  1156. // ADD R7,#Offset8
  1157. static INSN_REGPARM void thumb37(u32 opcode) { ADD_RN_O8(7); }
  1158.  
  1159. // SUB R0,#Offset8
  1160. static INSN_REGPARM void thumb38(u32 opcode) { SUB_RN_O8(0); }
  1161. // SUB R1,#Offset8
  1162. static INSN_REGPARM void thumb39(u32 opcode) { SUB_RN_O8(1); }
  1163. // SUB R2,#Offset8
  1164. static INSN_REGPARM void thumb3A(u32 opcode) { SUB_RN_O8(2); }
  1165. // SUB R3,#Offset8
  1166. static INSN_REGPARM void thumb3B(u32 opcode) { SUB_RN_O8(3); }
  1167. // SUB R4,#Offset8
  1168. static INSN_REGPARM void thumb3C(u32 opcode) { SUB_RN_O8(4); }
  1169. // SUB R5,#Offset8
  1170. static INSN_REGPARM void thumb3D(u32 opcode) { SUB_RN_O8(5); }
  1171. // SUB R6,#Offset8
  1172. static INSN_REGPARM void thumb3E(u32 opcode) { SUB_RN_O8(6); }
  1173. // SUB R7,#Offset8
  1174. static INSN_REGPARM void thumb3F(u32 opcode) { SUB_RN_O8(7); }
  1175.  
  1176. // ALU operations /////////////////////////////////////////////////////////
  1177.  
  1178. // AND Rd, Rs
  1179. static INSN_REGPARM void thumb40_0(u32 opcode)
  1180. {
  1181. int dest = opcode & 7;
  1182. reg[dest].I &= reg[(opcode >> 3)&7].I;
  1183. N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1184. Z_FLAG = reg[dest].I ? false : true;
  1185. THUMB_CONSOLE_OUTPUT(NULL, reg[2].I);
  1186. }
  1187.  
  1188. // EOR Rd, Rs
  1189. static INSN_REGPARM void thumb40_1(u32 opcode)
  1190. {
  1191. int dest = opcode & 7;
  1192. reg[dest].I ^= reg[(opcode >> 3)&7].I;
  1193. N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1194. Z_FLAG = reg[dest].I ? false : true;
  1195. }
  1196.  
  1197. // LSL Rd, Rs
  1198. static INSN_REGPARM void thumb40_2(u32 opcode)
  1199. {
  1200. int dest = opcode & 7;
  1201. u32 value = reg[(opcode >> 3)&7].B.B0;
  1202. if(value) {
  1203. if(value == 32) {
  1204. value = 0;
  1205. C_FLAG = (reg[dest].I & 1 ? true : false);
  1206. } else if(value < 32) {
  1207. LSL_RD_RS;
  1208. } else {
  1209. value = 0;
  1210. C_FLAG = false;
  1211. }
  1212. reg[dest].I = value;
  1213. }
  1214. N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1215. Z_FLAG = reg[dest].I ? false : true;
  1216. clockTicks = codeTicksAccess16(armNextPC)+2;
  1217. }
  1218.  
  1219. // LSR Rd, Rs
  1220. static INSN_REGPARM void thumb40_3(u32 opcode)
  1221. {
  1222. int dest = opcode & 7;
  1223. u32 value = reg[(opcode >> 3)&7].B.B0;
  1224. if(value) {
  1225. if(value == 32) {
  1226. value = 0;
  1227. C_FLAG = (reg[dest].I & 0x80000000 ? true : false);
  1228. } else if(value < 32) {
  1229. LSR_RD_RS;
  1230. } else {
  1231. value = 0;
  1232. C_FLAG = false;
  1233. }
  1234. reg[dest].I = value;
  1235. }
  1236. N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1237. Z_FLAG = reg[dest].I ? false : true;
  1238. clockTicks = codeTicksAccess16(armNextPC)+2;
  1239. }
  1240.  
  1241. // ASR Rd, Rs
  1242. static INSN_REGPARM void thumb41_0(u32 opcode)
  1243. {
  1244. int dest = opcode & 7;
  1245. u32 value = reg[(opcode >> 3)&7].B.B0;
  1246. if(value) {
  1247. if(value < 32) {
  1248. ASR_RD_RS;
  1249. reg[dest].I = value;
  1250. } else {
  1251. if(reg[dest].I & 0x80000000){
  1252. reg[dest].I = 0xFFFFFFFF;
  1253. C_FLAG = true;
  1254. } else {
  1255. reg[dest].I = 0x00000000;
  1256. C_FLAG = false;
  1257. }
  1258. }
  1259. }
  1260. N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1261. Z_FLAG = reg[dest].I ? false : true;
  1262. clockTicks = codeTicksAccess16(armNextPC)+2;
  1263. }
  1264.  
  1265. // ADC Rd, Rs
  1266. static INSN_REGPARM void thumb41_1(u32 opcode)
  1267. {
  1268. int dest = opcode & 0x07;
  1269. u32 value = reg[(opcode >> 3)&7].I;
  1270. ADC_RD_RS;
  1271. }
  1272.  
  1273. // SBC Rd, Rs
  1274. static INSN_REGPARM void thumb41_2(u32 opcode)
  1275. {
  1276. int dest = opcode & 0x07;
  1277. u32 value = reg[(opcode >> 3)&7].I;
  1278. SBC_RD_RS;
  1279. }
  1280.  
  1281. // ROR Rd, Rs
  1282. static INSN_REGPARM void thumb41_3(u32 opcode)
  1283. {
  1284. int dest = opcode & 7;
  1285. u32 value = reg[(opcode >> 3)&7].B.B0;
  1286.  
  1287. if(value) {
  1288. value = value & 0x1f;
  1289. if(value == 0) {
  1290. C_FLAG = (reg[dest].I & 0x80000000 ? true : false);
  1291. } else {
  1292. ROR_RD_RS;
  1293. reg[dest].I = value;
  1294. }
  1295. }
  1296. clockTicks = codeTicksAccess16(armNextPC)+2;
  1297. N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1298. Z_FLAG = reg[dest].I ? false : true;
  1299. }
  1300.  
  1301. // TST Rd, Rs
  1302. static INSN_REGPARM void thumb42_0(u32 opcode)
  1303. {
  1304. u32 value = reg[opcode & 7].I & reg[(opcode >> 3) & 7].I;
  1305. N_FLAG = value & 0x80000000 ? true : false;
  1306. Z_FLAG = value ? false : true;
  1307. }
  1308.  
  1309. // NEG Rd, Rs
  1310. static INSN_REGPARM void thumb42_1(u32 opcode)
  1311. {
  1312. int dest = opcode & 7;
  1313. int source = (opcode >> 3) & 7;
  1314. NEG_RD_RS;
  1315. }
  1316.  
  1317. // CMP Rd, Rs
  1318. static INSN_REGPARM void thumb42_2(u32 opcode)
  1319. {
  1320. int dest = opcode & 7;
  1321. u32 value = reg[(opcode >> 3)&7].I;
  1322. CMP_RD_RS;
  1323. }
  1324.  
  1325. // CMN Rd, Rs
  1326. static INSN_REGPARM void thumb42_3(u32 opcode)
  1327. {
  1328. int dest = opcode & 7;
  1329. u32 value = reg[(opcode >> 3)&7].I;
  1330. CMN_RD_RS;
  1331. }
  1332.  
  1333. // ORR Rd, Rs
  1334. static INSN_REGPARM void thumb43_0(u32 opcode)
  1335. {
  1336. int dest = opcode & 7;
  1337. reg[dest].I |= reg[(opcode >> 3) & 7].I;
  1338. Z_FLAG = reg[dest].I ? false : true;
  1339. N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1340. }
  1341.  
  1342. // MUL Rd, Rs
  1343. static INSN_REGPARM void thumb43_1(u32 opcode)
  1344. {
  1345. clockTicks = 1;
  1346. int dest = opcode & 7;
  1347. u32 rm = reg[dest].I;
  1348. reg[dest].I = reg[(opcode >> 3) & 7].I * rm;
  1349. if (((s32)rm) < 0)
  1350. rm = ~rm;
  1351. if ((rm & 0xFFFFFF00) == 0)
  1352. clockTicks += 0;
  1353. else if ((rm & 0xFFFF0000) == 0)
  1354. clockTicks += 1;
  1355. else if ((rm & 0xFF000000) == 0)
  1356. clockTicks += 2;
  1357. else
  1358. clockTicks += 3;
  1359. busPrefetchCount = (busPrefetchCount<<clockTicks) | (0xFF>>(8-clockTicks));
  1360. clockTicks += codeTicksAccess16(armNextPC) + 1;
  1361. Z_FLAG = reg[dest].I ? false : true;
  1362. N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1363. }
  1364.  
  1365. // BIC Rd, Rs
  1366. static INSN_REGPARM void thumb43_2(u32 opcode)
  1367. {
  1368. int dest = opcode & 7;
  1369. reg[dest].I &= (~reg[(opcode >> 3) & 7].I);
  1370. Z_FLAG = reg[dest].I ? false : true;
  1371. N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1372. }
  1373.  
  1374. // MVN Rd, Rs
  1375. static INSN_REGPARM void thumb43_3(u32 opcode)
  1376. {
  1377. int dest = opcode & 7;
  1378. reg[dest].I = ~reg[(opcode >> 3) & 7].I;
  1379. Z_FLAG = reg[dest].I ? false : true;
  1380. N_FLAG = reg[dest].I & 0x80000000 ? true : false;
  1381. }
  1382.  
  1383. // High-register instructions and BX //////////////////////////////////////
  1384.  
  1385. // ADD Rd, Hs
  1386. static INSN_REGPARM void thumb44_1(u32 opcode)
  1387. {
  1388. reg[opcode&7].I += reg[((opcode>>3)&7)+8].I;
  1389. }
  1390.  
  1391. // ADD Hd, Rs
  1392. static INSN_REGPARM void thumb44_2(u32 opcode)
  1393. {
  1394. reg[(opcode&7)+8].I += reg[(opcode>>3)&7].I;
  1395. if((opcode&7) == 7) {
  1396. reg[15].I &= 0xFFFFFFFE;
  1397. armNextPC = reg[15].I;
  1398. reg[15].I += 2;
  1399. THUMB_PREFETCH;
  1400. clockTicks = codeTicksAccessSeq16(armNextPC)*2
  1401. + codeTicksAccess16(armNextPC) + 3;
  1402. }
  1403. }
  1404.  
  1405. // ADD Hd, Hs
  1406. static INSN_REGPARM void thumb44_3(u32 opcode)
  1407. {
  1408. reg[(opcode&7)+8].I += reg[((opcode>>3)&7)+8].I;
  1409. if((opcode&7) == 7) {
  1410. reg[15].I &= 0xFFFFFFFE;
  1411. armNextPC = reg[15].I;
  1412. reg[15].I += 2;
  1413. THUMB_PREFETCH;
  1414. clockTicks = codeTicksAccessSeq16(armNextPC)*2
  1415. + codeTicksAccess16(armNextPC) + 3;
  1416. }
  1417. }
  1418.  
  1419. // CMP Rd, Hs
  1420. static INSN_REGPARM void thumb45_1(u32 opcode)
  1421. {
  1422. int dest = opcode & 7;
  1423. u32 value = reg[((opcode>>3)&7)+8].I;
  1424. CMP_RD_RS;
  1425. }
  1426.  
  1427. // CMP Hd, Rs
  1428. static INSN_REGPARM void thumb45_2(u32 opcode)
  1429. {
  1430. int dest = (opcode & 7) + 8;
  1431. u32 value = reg[(opcode>>3)&7].I;
  1432. CMP_RD_RS;
  1433. }
  1434.  
  1435. // CMP Hd, Hs
  1436. static INSN_REGPARM void thumb45_3(u32 opcode)
  1437. {
  1438. int dest = (opcode & 7) + 8;
  1439. u32 value = reg[((opcode>>3)&7)+8].I;
  1440. CMP_RD_RS;
  1441. }
  1442.  
  1443. // MOV Rd, Hs
  1444. static INSN_REGPARM void thumb46_1(u32 opcode)
  1445. {
  1446. reg[opcode&7].I = reg[((opcode>>3)&7)+8].I;
  1447. }
  1448.  
  1449. // MOV Hd, Rs
  1450. static INSN_REGPARM void thumb46_2(u32 opcode)
  1451. {
  1452. reg[(opcode&7)+8].I = reg[(opcode>>3)&7].I;
  1453. if((opcode&7) == 7) {
  1454. UPDATE_OLDREG;
  1455. reg[15].I &= 0xFFFFFFFE;
  1456. armNextPC = reg[15].I;
  1457. reg[15].I += 2;
  1458. THUMB_PREFETCH;
  1459. clockTicks = codeTicksAccessSeq16(armNextPC)*2
  1460. + codeTicksAccess16(armNextPC) + 3;
  1461. }
  1462. }
  1463.  
  1464. // MOV Hd, Hs
  1465. static INSN_REGPARM void thumb46_3(u32 opcode)
  1466. {
  1467. reg[(opcode&7)+8].I = reg[((opcode>>3)&7)+8].I;
  1468. if((opcode&7) == 7) {
  1469. UPDATE_OLDREG;
  1470. reg[15].I &= 0xFFFFFFFE;
  1471. armNextPC = reg[15].I;
  1472. reg[15].I += 2;
  1473. THUMB_PREFETCH;
  1474. clockTicks = codeTicksAccessSeq16(armNextPC)*2
  1475. + codeTicksAccess16(armNextPC) + 3;
  1476. }
  1477. }
  1478.  
  1479.  
  1480. // BX Rs
  1481. static INSN_REGPARM void thumb47(u32 opcode)
  1482. {
  1483. int base = (opcode >> 3) & 15;
  1484. busPrefetchCount=0;
  1485. UPDATE_OLDREG;
  1486. reg[15].I = reg[base].I;
  1487. if(reg[base].I & 1) {
  1488. armState = false;
  1489. reg[15].I &= 0xFFFFFFFE;
  1490. armNextPC = reg[15].I;
  1491. reg[15].I += 2;
  1492. THUMB_PREFETCH;
  1493. clockTicks = codeTicksAccessSeq16(armNextPC)
  1494. + codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 3;
  1495. } else {
  1496. armState = true;
  1497. reg[15].I &= 0xFFFFFFFC;
  1498. armNextPC = reg[15].I;
  1499. reg[15].I += 4;
  1500. ARM_PREFETCH;
  1501. clockTicks = codeTicksAccessSeq32(armNextPC)
  1502. + codeTicksAccessSeq32(armNextPC) + codeTicksAccess32(armNextPC) + 3;
  1503. }
  1504. }
  1505.  
  1506. // Load/store instructions ////////////////////////////////////////////////
  1507.  
  1508. // LDR R0~R7,[PC, #Imm]
  1509. static INSN_REGPARM void thumb48(u32 opcode)
  1510. {
  1511. u8 regist = (opcode >> 8) & 7;
  1512. if (busPrefetchCount == 0)
  1513. busPrefetch = busPrefetchEnable;
  1514. u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
  1515. reg[regist].I = CPUReadMemoryQuick(address);
  1516. busPrefetchCount=0;
  1517. clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
  1518. }
  1519.  
  1520. // STR Rd, [Rs, Rn]
  1521. static INSN_REGPARM void thumb50(u32 opcode)
  1522. {
  1523. if (busPrefetchCount == 0)
  1524. busPrefetch = busPrefetchEnable;
  1525. u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
  1526. CPUWriteMemory(address, reg[opcode & 7].I);
  1527. clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
  1528. }
  1529.  
  1530. // STRH Rd, [Rs, Rn]
  1531. static INSN_REGPARM void thumb52(u32 opcode)
  1532. {
  1533. if (busPrefetchCount == 0)
  1534. busPrefetch = busPrefetchEnable;
  1535. u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
  1536. CPUWriteHalfWord(address, reg[opcode&7].W.W0);
  1537. clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
  1538. }
  1539.  
  1540. // STRB Rd, [Rs, Rn]
  1541. static INSN_REGPARM void thumb54(u32 opcode)
  1542. {
  1543. if (busPrefetchCount == 0)
  1544. busPrefetch = busPrefetchEnable;
  1545. u32 address = reg[(opcode>>3)&7].I + reg[(opcode >>6)&7].I;
  1546. CPUWriteByte(address, reg[opcode & 7].B.B0);
  1547. clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
  1548. }
  1549.  
  1550. // LDSB Rd, [Rs, Rn]
  1551. static INSN_REGPARM void thumb56(u32 opcode)
  1552. {
  1553. if (busPrefetchCount == 0)
  1554. busPrefetch = busPrefetchEnable;
  1555. u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
  1556. reg[opcode&7].I = (s8)CPUReadByte(address);
  1557. clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
  1558. }
  1559.  
  1560. // LDR Rd, [Rs, Rn]
  1561. static INSN_REGPARM void thumb58(u32 opcode)
  1562. {
  1563. if (busPrefetchCount == 0)
  1564. busPrefetch = busPrefetchEnable;
  1565. u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
  1566. reg[opcode&7].I = CPUReadMemory(address);
  1567. clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
  1568. }
  1569.  
  1570. // LDRH Rd, [Rs, Rn]
  1571. static INSN_REGPARM void thumb5A(u32 opcode)
  1572. {
  1573. if (busPrefetchCount == 0)
  1574. busPrefetch = busPrefetchEnable;
  1575. u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
  1576. reg[opcode&7].I = CPUReadHalfWord(address);
  1577. clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
  1578. }
  1579.  
  1580. // LDRB Rd, [Rs, Rn]
  1581. static INSN_REGPARM void thumb5C(u32 opcode)
  1582. {
  1583. if (busPrefetchCount == 0)
  1584. busPrefetch = busPrefetchEnable;
  1585. u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
  1586. reg[opcode&7].I = CPUReadByte(address);
  1587. clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
  1588. }
  1589.  
  1590. // LDSH Rd, [Rs, Rn]
  1591. static INSN_REGPARM void thumb5E(u32 opcode)
  1592. {
  1593. if (busPrefetchCount == 0)
  1594. busPrefetch = busPrefetchEnable;
  1595. u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
  1596. reg[opcode&7].I = (s16)CPUReadHalfWordSigned(address);
  1597. clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
  1598. }
  1599.  
  1600. // STR Rd, [Rs, #Imm]
  1601. static INSN_REGPARM void thumb60(u32 opcode)
  1602. {
  1603. if (busPrefetchCount == 0)
  1604. busPrefetch = busPrefetchEnable;
  1605. u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2);
  1606. CPUWriteMemory(address, reg[opcode&7].I);
  1607. clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
  1608. }
  1609.  
  1610. // LDR Rd, [Rs, #Imm]
  1611. static INSN_REGPARM void thumb68(u32 opcode)
  1612. {
  1613. if (busPrefetchCount == 0)
  1614. busPrefetch = busPrefetchEnable;
  1615. u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2);
  1616. reg[opcode&7].I = CPUReadMemory(address);
  1617. clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
  1618. }
  1619.  
  1620. // STRB Rd, [Rs, #Imm]
  1621. static INSN_REGPARM void thumb70(u32 opcode)
  1622. {
  1623. if (busPrefetchCount == 0)
  1624. busPrefetch = busPrefetchEnable;
  1625. u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31));
  1626. CPUWriteByte(address, reg[opcode&7].B.B0);
  1627. clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
  1628. }
  1629.  
  1630. // LDRB Rd, [Rs, #Imm]
  1631. static INSN_REGPARM void thumb78(u32 opcode)
  1632. {
  1633. if (busPrefetchCount == 0)
  1634. busPrefetch = busPrefetchEnable;
  1635. u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31));
  1636. reg[opcode&7].I = CPUReadByte(address);
  1637. clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
  1638. }
  1639.  
  1640. // STRH Rd, [Rs, #Imm]
  1641. static INSN_REGPARM void thumb80(u32 opcode)
  1642. {
  1643. if (busPrefetchCount == 0)
  1644. busPrefetch = busPrefetchEnable;
  1645. u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1);
  1646. CPUWriteHalfWord(address, reg[opcode&7].W.W0);
  1647. clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
  1648. }
  1649.  
  1650. // LDRH Rd, [Rs, #Imm]
  1651. static INSN_REGPARM void thumb88(u32 opcode)
  1652. {
  1653. if (busPrefetchCount == 0)
  1654. busPrefetch = busPrefetchEnable;
  1655. u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1);
  1656. reg[opcode&7].I = CPUReadHalfWord(address);
  1657. clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
  1658. }
  1659.  
  1660. // STR R0~R7, [SP, #Imm]
  1661. static INSN_REGPARM void thumb90(u32 opcode)
  1662. {
  1663. u8 regist = (opcode >> 8) & 7;
  1664. if (busPrefetchCount == 0)
  1665. busPrefetch = busPrefetchEnable;
  1666. u32 address = reg[13].I + ((opcode&255)<<2);
  1667. CPUWriteMemory(address, reg[regist].I);
  1668. clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
  1669. }
  1670.  
  1671. // LDR R0~R7, [SP, #Imm]
  1672. static INSN_REGPARM void thumb98(u32 opcode)
  1673. {
  1674. u8 regist = (opcode >> 8) & 7;
  1675. if (busPrefetchCount == 0)
  1676. busPrefetch = busPrefetchEnable;
  1677. u32 address = reg[13].I + ((opcode&255)<<2);
  1678. reg[regist].I = CPUReadMemoryQuick(address);
  1679. clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
  1680. }
  1681.  
  1682. // PC/stack-related ///////////////////////////////////////////////////////
  1683.  
  1684. // ADD R0~R7, PC, Imm
  1685. static INSN_REGPARM void thumbA0(u32 opcode)
  1686. {
  1687. u8 regist = (opcode >> 8) & 7;
  1688. reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
  1689. }
  1690.  
  1691. // ADD R0~R7, SP, Imm
  1692. static INSN_REGPARM void thumbA8(u32 opcode)
  1693. {
  1694. u8 regist = (opcode >> 8) & 7;
  1695. reg[regist].I = reg[13].I + ((opcode&255)<<2);
  1696. }
  1697.  
  1698. // ADD SP, Imm
  1699. static INSN_REGPARM void thumbB0(u32 opcode)
  1700. {
  1701. int offset = (opcode & 127) << 2;
  1702. if(opcode & 0x80)
  1703. offset = -offset;
  1704. reg[13].I += offset;
  1705. }
  1706.  
  1707. // Push and pop ///////////////////////////////////////////////////////////
  1708.  
  1709. #define PUSH_REG(val, r) \
  1710. if (opcode & (val)) { \
  1711. CPUWriteMemory(address, reg[(r)].I); \
  1712. if (!count) { \
  1713. clockTicks += 1 + dataTicksAccess32(address); \
  1714. } else { \
  1715. clockTicks += 1 + dataTicksAccessSeq32(address); \
  1716. } \
  1717. count++; \
  1718. address += 4; \
  1719. }
  1720.  
  1721. #define POP_REG(val, r) \
  1722. if (opcode & (val)) { \
  1723. reg[(r)].I = CPUReadMemory(address); \
  1724. if (!count) { \
  1725. clockTicks += 1 + dataTicksAccess32(address); \
  1726. } else { \
  1727. clockTicks += 1 + dataTicksAccessSeq32(address); \
  1728. } \
  1729. count++; \
  1730. address += 4; \
  1731. }
  1732.  
  1733. // PUSH {Rlist}
  1734. static INSN_REGPARM void thumbB4(u32 opcode)
  1735. {
  1736. if (busPrefetchCount == 0)
  1737. busPrefetch = busPrefetchEnable;
  1738. int count = 0;
  1739. u32 temp = reg[13].I - 4 * cpuBitsSet[opcode & 0xff];
  1740. u32 address = temp & 0xFFFFFFFC;
  1741. PUSH_REG(1, 0);
  1742. PUSH_REG(2, 1);
  1743. PUSH_REG(4, 2);
  1744. PUSH_REG(8, 3);
  1745. PUSH_REG(16, 4);
  1746. PUSH_REG(32, 5);
  1747. PUSH_REG(64, 6);
  1748. PUSH_REG(128, 7);
  1749. clockTicks += 1 + codeTicksAccess16(armNextPC);
  1750. reg[13].I = temp;
  1751. }
  1752.  
  1753. // PUSH {Rlist, LR}
  1754. static INSN_REGPARM void thumbB5(u32 opcode)
  1755. {
  1756. if (busPrefetchCount == 0)
  1757. busPrefetch = busPrefetchEnable;
  1758. int count = 0;
  1759. u32 temp = reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff];
  1760. u32 address = temp & 0xFFFFFFFC;
  1761. PUSH_REG(1, 0);
  1762. PUSH_REG(2, 1);
  1763. PUSH_REG(4, 2);
  1764. PUSH_REG(8, 3);
  1765. PUSH_REG(16, 4);
  1766. PUSH_REG(32, 5);
  1767. PUSH_REG(64, 6);
  1768. PUSH_REG(128, 7);
  1769. PUSH_REG(256, 14);
  1770. clockTicks += 1 + codeTicksAccess16(armNextPC);
  1771. reg[13].I = temp;
  1772. }
  1773.  
  1774. // POP {Rlist}
  1775. static INSN_REGPARM void thumbBC(u32 opcode)
  1776. {
  1777. if (busPrefetchCount == 0)
  1778. busPrefetch = busPrefetchEnable;
  1779. int count = 0;
  1780. u32 address = reg[13].I & 0xFFFFFFFC;
  1781. u32 temp = reg[13].I + 4*cpuBitsSet[opcode & 0xFF];
  1782. POP_REG(1, 0);
  1783. POP_REG(2, 1);
  1784. POP_REG(4, 2);
  1785. POP_REG(8, 3);
  1786. POP_REG(16, 4);
  1787. POP_REG(32, 5);
  1788. POP_REG(64, 6);
  1789. POP_REG(128, 7);
  1790. reg[13].I = temp;
  1791. clockTicks = 2 + codeTicksAccess16(armNextPC);
  1792. }
  1793.  
  1794. // POP {Rlist, PC}
  1795. static INSN_REGPARM void thumbBD(u32 opcode)
  1796. {
  1797. if (busPrefetchCount == 0)
  1798. busPrefetch = busPrefetchEnable;
  1799. int count = 0;
  1800. u32 address = reg[13].I & 0xFFFFFFFC;
  1801. u32 temp = reg[13].I + 4 + 4*cpuBitsSet[opcode & 0xFF];
  1802. POP_REG(1, 0);
  1803. POP_REG(2, 1);
  1804. POP_REG(4, 2);
  1805. POP_REG(8, 3);
  1806. POP_REG(16, 4);
  1807. POP_REG(32, 5);
  1808. POP_REG(64, 6);
  1809. POP_REG(128, 7);
  1810. reg[15].I = (CPUReadMemory(address) & 0xFFFFFFFE);
  1811. if (!count) {
  1812. clockTicks += 1 + dataTicksAccess32(address);
  1813. } else {
  1814. clockTicks += 1 + dataTicksAccessSeq32(address);
  1815. }
  1816. count++;
  1817. armNextPC = reg[15].I;
  1818. reg[15].I += 2;
  1819. reg[13].I = temp;
  1820. THUMB_PREFETCH;
  1821. busPrefetchCount = 0;
  1822. clockTicks += 3 + codeTicksAccess16(armNextPC) + codeTicksAccess16(armNextPC);
  1823. }
  1824.  
  1825. // Load/store multiple ////////////////////////////////////////////////////
  1826.  
  1827. #define THUMB_STM_REG(val,r,b) \
  1828. if(opcode & (val)) { \
  1829. CPUWriteMemory(address, reg[(r)].I); \
  1830. reg[(b)].I = temp; \
  1831. if (!count) { \
  1832. clockTicks += 1 + dataTicksAccess32(address); \
  1833. } else { \
  1834. clockTicks += 1 + dataTicksAccessSeq32(address); \
  1835. } \
  1836. count++; \
  1837. address += 4; \
  1838. }
  1839.  
  1840. #define THUMB_LDM_REG(val,r) \
  1841. if(opcode & (val)) { \
  1842. reg[(r)].I = CPUReadMemory(address); \
  1843. if (!count) { \
  1844. clockTicks += 1 + dataTicksAccess32(address); \
  1845. } else { \
  1846. clockTicks += 1 + dataTicksAccessSeq32(address); \
  1847. } \
  1848. count++; \
  1849. address += 4; \
  1850. }
  1851.  
  1852. // STM R0~7!, {Rlist}
  1853. static INSN_REGPARM void thumbC0(u32 opcode)
  1854. {
  1855. u8 regist = (opcode >> 8) & 7;
  1856. if (busPrefetchCount == 0)
  1857. busPrefetch = busPrefetchEnable;
  1858. u32 address = reg[regist].I & 0xFFFFFFFC;
  1859. u32 temp = reg[regist].I + 4*cpuBitsSet[opcode & 0xff];
  1860. int count = 0;
  1861. // store
  1862. THUMB_STM_REG(1, 0, regist);
  1863. THUMB_STM_REG(2, 1, regist);
  1864. THUMB_STM_REG(4, 2, regist);
  1865. THUMB_STM_REG(8, 3, regist);
  1866. THUMB_STM_REG(16, 4, regist);
  1867. THUMB_STM_REG(32, 5, regist);
  1868. THUMB_STM_REG(64, 6, regist);
  1869. THUMB_STM_REG(128, 7, regist);
  1870. clockTicks = 1 + codeTicksAccess16(armNextPC);
  1871. }
  1872.  
  1873. // LDM R0~R7!, {Rlist}
  1874. static INSN_REGPARM void thumbC8(u32 opcode)
  1875. {
  1876. u8 regist = (opcode >> 8) & 7;
  1877. if (busPrefetchCount == 0)
  1878. busPrefetch = busPrefetchEnable;
  1879. u32 address = reg[regist].I & 0xFFFFFFFC;
  1880. u32 temp = reg[regist].I + 4*cpuBitsSet[opcode & 0xFF];
  1881. int count = 0;
  1882. // load
  1883. THUMB_LDM_REG(1, 0);
  1884. THUMB_LDM_REG(2, 1);
  1885. THUMB_LDM_REG(4, 2);
  1886. THUMB_LDM_REG(8, 3);
  1887. THUMB_LDM_REG(16, 4);
  1888. THUMB_LDM_REG(32, 5);
  1889. THUMB_LDM_REG(64, 6);
  1890. THUMB_LDM_REG(128, 7);
  1891. clockTicks = 2 + codeTicksAccess16(armNextPC);
  1892. if(!(opcode & (1<<regist)))
  1893. reg[regist].I = temp;
  1894. }
  1895.  
  1896. // Conditional branches ///////////////////////////////////////////////////
  1897.  
  1898. // BEQ offset
  1899. static INSN_REGPARM void thumbD0(u32 opcode)
  1900. {
  1901. UPDATE_OLDREG;
  1902. if(Z_FLAG) {
  1903. reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1904. armNextPC = reg[15].I;
  1905. reg[15].I += 2;
  1906. THUMB_PREFETCH;
  1907. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
  1908. codeTicksAccess16(armNextPC)+3;
  1909. busPrefetchCount=0;
  1910. }
  1911. }
  1912.  
  1913. // BNE offset
  1914. static INSN_REGPARM void thumbD1(u32 opcode)
  1915. {
  1916. UPDATE_OLDREG;
  1917. if(!Z_FLAG) {
  1918. reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1919. armNextPC = reg[15].I;
  1920. reg[15].I += 2;
  1921. THUMB_PREFETCH;
  1922. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
  1923. codeTicksAccess16(armNextPC)+3;
  1924. busPrefetchCount=0;
  1925. }
  1926. }
  1927.  
  1928. // BCS offset
  1929. static INSN_REGPARM void thumbD2(u32 opcode)
  1930. {
  1931. UPDATE_OLDREG;
  1932. if(C_FLAG) {
  1933. reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1934. armNextPC = reg[15].I;
  1935. reg[15].I += 2;
  1936. THUMB_PREFETCH;
  1937. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
  1938. codeTicksAccess16(armNextPC)+3;
  1939. busPrefetchCount=0;
  1940. }
  1941. }
  1942.  
  1943. // BCC offset
  1944. static INSN_REGPARM void thumbD3(u32 opcode)
  1945. {
  1946. UPDATE_OLDREG;
  1947. if(!C_FLAG) {
  1948. reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1949. armNextPC = reg[15].I;
  1950. reg[15].I += 2;
  1951. THUMB_PREFETCH;
  1952. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
  1953. codeTicksAccess16(armNextPC)+3;
  1954. busPrefetchCount=0;
  1955. }
  1956. }
  1957.  
  1958. // BMI offset
  1959. static INSN_REGPARM void thumbD4(u32 opcode)
  1960. {
  1961. UPDATE_OLDREG;
  1962. if(N_FLAG) {
  1963. reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1964. armNextPC = reg[15].I;
  1965. reg[15].I += 2;
  1966. THUMB_PREFETCH;
  1967. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
  1968. codeTicksAccess16(armNextPC)+3;
  1969. busPrefetchCount=0;
  1970. }
  1971. }
  1972.  
  1973. // BPL offset
  1974. static INSN_REGPARM void thumbD5(u32 opcode)
  1975. {
  1976. UPDATE_OLDREG;
  1977. if(!N_FLAG) {
  1978. reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1979. armNextPC = reg[15].I;
  1980. reg[15].I += 2;
  1981. THUMB_PREFETCH;
  1982. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
  1983. codeTicksAccess16(armNextPC)+3;
  1984. busPrefetchCount=0;
  1985. }
  1986. }
  1987.  
  1988. // BVS offset
  1989. static INSN_REGPARM void thumbD6(u32 opcode)
  1990. {
  1991. UPDATE_OLDREG;
  1992. if(V_FLAG) {
  1993. reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  1994. armNextPC = reg[15].I;
  1995. reg[15].I += 2;
  1996. THUMB_PREFETCH;
  1997. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
  1998. codeTicksAccess16(armNextPC)+3;
  1999. busPrefetchCount=0;
  2000. }
  2001. }
  2002.  
  2003. // BVC offset
  2004. static INSN_REGPARM void thumbD7(u32 opcode)
  2005. {
  2006. UPDATE_OLDREG;
  2007. if(!V_FLAG) {
  2008. reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  2009. armNextPC = reg[15].I;
  2010. reg[15].I += 2;
  2011. THUMB_PREFETCH;
  2012. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
  2013. codeTicksAccess16(armNextPC)+3;
  2014. busPrefetchCount=0;
  2015. }
  2016. }
  2017.  
  2018. // BHI offset
  2019. static INSN_REGPARM void thumbD8(u32 opcode)
  2020. {
  2021. UPDATE_OLDREG;
  2022. if(C_FLAG && !Z_FLAG) {
  2023. reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  2024. armNextPC = reg[15].I;
  2025. reg[15].I += 2;
  2026. THUMB_PREFETCH;
  2027. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
  2028. codeTicksAccess16(armNextPC)+3;
  2029. busPrefetchCount=0;
  2030. }
  2031. }
  2032.  
  2033. // BLS offset
  2034. static INSN_REGPARM void thumbD9(u32 opcode)
  2035. {
  2036. UPDATE_OLDREG;
  2037. if(!C_FLAG || Z_FLAG) {
  2038. reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  2039. armNextPC = reg[15].I;
  2040. reg[15].I += 2;
  2041. THUMB_PREFETCH;
  2042. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
  2043. codeTicksAccess16(armNextPC)+3;
  2044. busPrefetchCount=0;
  2045. }
  2046. }
  2047.  
  2048. // BGE offset
  2049. static INSN_REGPARM void thumbDA(u32 opcode)
  2050. {
  2051. UPDATE_OLDREG;
  2052. if(N_FLAG == V_FLAG) {
  2053. reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  2054. armNextPC = reg[15].I;
  2055. reg[15].I += 2;
  2056. THUMB_PREFETCH;
  2057. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
  2058. codeTicksAccess16(armNextPC)+3;
  2059. busPrefetchCount=0;
  2060. }
  2061. }
  2062.  
  2063. // BLT offset
  2064. static INSN_REGPARM void thumbDB(u32 opcode)
  2065. {
  2066. UPDATE_OLDREG;
  2067. if(N_FLAG != V_FLAG) {
  2068. reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  2069. armNextPC = reg[15].I;
  2070. reg[15].I += 2;
  2071. THUMB_PREFETCH;
  2072. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
  2073. codeTicksAccess16(armNextPC)+3;
  2074. busPrefetchCount=0;
  2075. }
  2076. }
  2077.  
  2078. // BGT offset
  2079. static INSN_REGPARM void thumbDC(u32 opcode)
  2080. {
  2081. UPDATE_OLDREG;
  2082. if(!Z_FLAG && (N_FLAG == V_FLAG)) {
  2083. reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  2084. armNextPC = reg[15].I;
  2085. reg[15].I += 2;
  2086. THUMB_PREFETCH;
  2087. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
  2088. codeTicksAccess16(armNextPC)+3;
  2089. busPrefetchCount=0;
  2090. }
  2091. }
  2092.  
  2093. // BLE offset
  2094. static INSN_REGPARM void thumbDD(u32 opcode)
  2095. {
  2096. UPDATE_OLDREG;
  2097. if(Z_FLAG || (N_FLAG != V_FLAG)) {
  2098. reg[15].I += ((s8)(opcode & 0xFF)) << 1;
  2099. armNextPC = reg[15].I;
  2100. reg[15].I += 2;
  2101. THUMB_PREFETCH;
  2102. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
  2103. codeTicksAccess16(armNextPC)+3;
  2104. busPrefetchCount=0;
  2105. }
  2106. }
  2107.  
  2108. // SWI, B, BL /////////////////////////////////////////////////////////////
  2109.  
  2110. // SWI #comment
  2111. static INSN_REGPARM void thumbDF(u32 opcode)
  2112. {
  2113. u32 address = 0;
  2114. clockTicks = codeTicksAccessSeq16(address) + codeTicksAccessSeq16(address) +
  2115. codeTicksAccess16(address)+3;
  2116. busPrefetchCount=0;
  2117. CPUSoftwareInterrupt(opcode & 0xFF);
  2118. }
  2119.  
  2120. // B offset
  2121. static INSN_REGPARM void thumbE0(u32 opcode)
  2122. {
  2123. int offset = (opcode & 0x3FF) << 1;
  2124. if(opcode & 0x0400)
  2125. offset |= 0xFFFFF800;
  2126. reg[15].I += offset;
  2127. armNextPC = reg[15].I;
  2128. reg[15].I += 2;
  2129. THUMB_PREFETCH;
  2130. clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNex
Add Comment
Please, Sign In to add comment