A MOS 6502 emulator written in C with a focus on speed, especially for ARM targets.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

1029 lignes
30KB

  1. #include "e6502.h"
  2. #ifdef E6502_DEBUG
  3. #include <stdio.h>
  4. #include "opcodes.h"
  5. #endif
  6. // Instruction Addressing
  7. #ifdef E6502_POLL_MEM
  8. typedef uint8_t* e6502_Address;
  9. static inline e6502_Address e6502_mem_adr(e6502_Core* core,
  10. e6502_Mem_Addr adr) {
  11. return &core->memory[adr];
  12. }
  13. static inline e6502_Mem_Addr e6502_adr_mem(e6502_Core* core,
  14. e6502_Address adr) {
  15. return (adr - core->memory);
  16. }
  17. static inline uint8_t e6502_adr_r8(e6502_Core* core,
  18. e6502_Address adr) {
  19. return adr[0];
  20. }
  21. static inline uint8_t e6502_adr_r16(e6502_Core* core,
  22. e6502_Address adr) {
  23. return (adr[0] | ((uint16_t)adr[1] << 8));
  24. }
  25. static inline void e6502_adr_w8(e6502_Core* core,
  26. e6502_Address adr,
  27. uint8_t val) {
  28. adr[0] = val;
  29. }
  30. static inline void e6502_adr_w16(e6502_Core* core,
  31. e6502_Address adr,
  32. uint16_t val) {
  33. adr[0] = val;
  34. adr[1] = val >> 8;
  35. }
  36. #else // !E6502_POLL_MEM
  37. typedef uint16_t e6502_Address;
  38. static inline e6502_Address e6502_mem_adr(e6502_Core* core,
  39. e6502_Mem_Addr adr) {
  40. return adr;
  41. }
  42. static inline e6502_Mem_Addr e6502_adr_mem(e6502_Core* core,
  43. e6502_Address adr) {
  44. return adr;
  45. }
  46. static inline uint8_t e6502_adr_r8(e6502_Core* core,
  47. e6502_Address adr) {
  48. return e6502_r8(core, adr);
  49. }
  50. static inline void e6502_adr_w8(e6502_Core* core,
  51. e6502_Address adr,
  52. uint8_t val) {
  53. e6502_w8(core, adr, val);
  54. }
  55. #endif // !E6502_POLL_MEM
  56. // Read values after opcodes
  57. static inline uint8_t arg8(e6502_Core* core) {
  58. return e6502_r8(core, core->registers.PC++);
  59. }
  60. static inline uint16_t arg16(e6502_Core* core) {
  61. return (arg8(core) | ((uint16_t)arg8(core) << 8));
  62. }
  63. // Interpret opcode values
  64. static inline e6502_Address adr_imp(e6502_Core* core) {
  65. return 0;
  66. }
  67. static inline e6502_Address adr_acc(e6502_Core* core) {
  68. return 0;
  69. }
  70. static inline e6502_Address adr_ind(e6502_Core* core) {
  71. return e6502_mem_adr(core, e6502_r16(core, arg16(core)));
  72. }
  73. static inline e6502_Address adr_ind_x(e6502_Core* core) {
  74. return e6502_mem_adr(core, e6502_r16(
  75. core,
  76. (uint8_t)(core->registers.X + arg8(core))
  77. ));
  78. }
  79. static inline e6502_Address adr_ind_y(e6502_Core* core) {
  80. uint16_t zp_adr = e6502_r16(core, arg8(core));
  81. uint8_t old_page = zp_adr >> 8;
  82. uint16_t new_adr = core->registers.Y + zp_adr;
  83. if (new_adr >> 8 != old_page) core->cycle++;
  84. return e6502_mem_adr(core, new_adr);
  85. }
  86. static inline e6502_Address adr_abs_i(e6502_Core* core,
  87. uint8_t i) {
  88. uint16_t abs_adr = arg16(core);
  89. uint8_t old_page = abs_adr >> 8;
  90. uint16_t new_adr = i + abs_adr;
  91. if (new_adr >> 8 != old_page) core->cycle++;
  92. return e6502_mem_adr(core, new_adr);
  93. }
  94. static inline e6502_Address adr_abs_x(e6502_Core* core) {
  95. return adr_abs_i(core, core->registers.X);
  96. }
  97. static inline e6502_Address adr_abs_y(e6502_Core* core) {
  98. return adr_abs_i(core, core->registers.Y);
  99. }
  100. static inline e6502_Address adr_zp(e6502_Core* core) {
  101. return e6502_mem_adr(core, arg8(core));
  102. }
  103. static inline e6502_Address adr_zp_x(e6502_Core* core) {
  104. return e6502_mem_adr(
  105. core, (uint8_t)(arg8(core) + core->registers.X)
  106. );
  107. }
  108. static inline e6502_Address adr_zp_y(e6502_Core* core) {
  109. return e6502_mem_adr(
  110. core, (uint8_t)(arg8(core) + core->registers.Y)
  111. );
  112. }
  113. static inline e6502_Address adr_abs(e6502_Core* core) {
  114. return e6502_mem_adr(core, arg16(core));
  115. }
  116. static inline e6502_Address adr_imm(e6502_Core* core) {
  117. return e6502_mem_adr(core, core->registers.PC++);
  118. }
  119. static inline e6502_Address adr_rel(e6502_Core* core) {
  120. return e6502_mem_adr(
  121. core, (int8_t)arg8(core) + core->registers.PC
  122. );
  123. }
  124. // Instructions
  125. static inline void nop(e6502_Core* core, e6502_Address adr) {
  126. // NOP
  127. }
  128. static inline void brk(e6502_Core *core, e6502_Address adr) {
  129. e6502_push16(core, core->registers.PC + 1);
  130. e6502_push8(core, core->registers.P |
  131. e6502_Status_1 |
  132. e6502_Status_B);
  133. core->registers.P |= e6502_Status_I;
  134. core->registers.PC = e6502_r16(core, e6502_IRQ_Vec);
  135. }
  136. static inline void rti(e6502_Core *core, e6502_Address adr) {
  137. core->registers.P = e6502_pop8(core) |
  138. e6502_Status_1 |
  139. e6502_Status_B;
  140. core->registers.PC = e6502_pop16(core);
  141. }
  142. static inline void ora(e6502_Core *core, e6502_Address adr) {
  143. core->registers.A |= e6502_adr_r8(core, adr);
  144. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  145. core->registers.P |= (core->registers.A & e6502_Status_N);
  146. if (!core->registers.A) core->registers.P |= e6502_Status_Z;
  147. }
  148. static inline void eor(e6502_Core *core, e6502_Address adr) {
  149. core->registers.A ^= e6502_adr_r8(core, adr);
  150. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  151. core->registers.P |= (core->registers.A & e6502_Status_N);
  152. if (!core->registers.A) core->registers.P |= e6502_Status_Z;
  153. }
  154. static inline void asl(e6502_Core *core, e6502_Address adr) {
  155. // TODO: Emulate double-read or double-write
  156. uint8_t val = e6502_adr_r8(core, adr);
  157. core->registers.P &= ~(e6502_Status_C |
  158. e6502_Status_Z |
  159. e6502_Status_N);
  160. if (val & 0x80) core->registers.P |= e6502_Status_C;
  161. val <<= 1;
  162. core->registers.P |= (val & e6502_Status_N);
  163. if (!val) core->registers.P |= e6502_Status_Z;
  164. e6502_adr_w8(core, adr, val);
  165. }
  166. static inline void asl_a(e6502_Core *core, e6502_Address adr) {
  167. uint8_t val = core->registers.A;
  168. core->registers.P &= ~(e6502_Status_C |
  169. e6502_Status_Z |
  170. e6502_Status_N);
  171. if (val & 0x80) core->registers.P |= e6502_Status_C;
  172. val <<= 1;
  173. core->registers.P |= (val & e6502_Status_N);
  174. if (!val) core->registers.P |= e6502_Status_Z;
  175. core->registers.A = val;
  176. }
  177. static inline void lsr(e6502_Core *core, e6502_Address adr) {
  178. // TODO: Emulate double-read or double-write
  179. uint8_t val = e6502_adr_r8(core, adr);
  180. core->registers.P &= ~(e6502_Status_C |
  181. e6502_Status_Z |
  182. e6502_Status_N);
  183. core->registers.P |= (val & e6502_Status_C);
  184. val >>= 1;
  185. core->registers.P |= (val & e6502_Status_N);
  186. if (!val) core->registers.P |= e6502_Status_Z;
  187. e6502_adr_w8(core, adr, val);
  188. }
  189. static inline void lsr_a(e6502_Core *core, e6502_Address adr) {
  190. uint8_t val = core->registers.A;
  191. core->registers.P &= ~(e6502_Status_C |
  192. e6502_Status_Z |
  193. e6502_Status_N);
  194. core->registers.P |= (val & e6502_Status_C);
  195. val >>= 1;
  196. core->registers.P |= (val & e6502_Status_N);
  197. if (!val) core->registers.P |= e6502_Status_Z;
  198. core->registers.A = val;
  199. }
  200. static inline void rol(e6502_Core *core, e6502_Address adr) {
  201. // TODO: Emulate double-read or double-write
  202. uint8_t val = e6502_adr_r8(core, adr);
  203. uint8_t new_c = (val & 0x80) ? e6502_Status_C : 0;
  204. val <<= 1;
  205. val |= (core->registers.P & e6502_Status_C);
  206. core->registers.P &= ~(e6502_Status_C |
  207. e6502_Status_Z |
  208. e6502_Status_N);
  209. core->registers.P |= new_c;
  210. if (!val) core->registers.P |= e6502_Status_Z;
  211. core->registers.P |= (val & e6502_Status_N);
  212. e6502_adr_w8(core, adr, val);
  213. }
  214. static inline void rol_a(e6502_Core *core, e6502_Address adr) {
  215. uint8_t val = core->registers.A;
  216. uint8_t new_c = (val & 0x80) ? e6502_Status_C : 0;
  217. val <<= 1;
  218. val |= (core->registers.P & e6502_Status_C);
  219. core->registers.P &= ~(e6502_Status_C |
  220. e6502_Status_Z |
  221. e6502_Status_N);
  222. core->registers.P |= new_c;
  223. if (!val) core->registers.P |= e6502_Status_Z;
  224. core->registers.P |= (val & e6502_Status_N);
  225. core->registers.A = val;
  226. }
  227. static inline void ror(e6502_Core *core, e6502_Address adr) {
  228. // TODO: Emulate double-read or double-write
  229. uint8_t val = e6502_adr_r8(core, adr);
  230. uint8_t new_c = (val & e6502_Status_C);
  231. val >>= 1;
  232. if (core->registers.P & e6502_Status_C) val |= e6502_Status_N;
  233. core->registers.P &= ~(e6502_Status_C |
  234. e6502_Status_Z |
  235. e6502_Status_N);
  236. core->registers.P |= new_c;
  237. if (!val) core->registers.P |= e6502_Status_Z;
  238. core->registers.P |= (val & e6502_Status_N);
  239. e6502_adr_w8(core, adr, val);
  240. }
  241. static inline void ror_a(e6502_Core *core, e6502_Address adr) {
  242. uint8_t val = core->registers.A;
  243. uint8_t new_c = (val & e6502_Status_C);
  244. val >>= 1;
  245. if (core->registers.P & e6502_Status_C) val |= e6502_Status_N;
  246. core->registers.P &= ~(e6502_Status_C |
  247. e6502_Status_Z |
  248. e6502_Status_N);
  249. core->registers.P |= new_c;
  250. if (!val) core->registers.P |= e6502_Status_Z;
  251. core->registers.P |= (val & e6502_Status_N);
  252. core->registers.A = val;
  253. }
  254. static inline void pha(e6502_Core *core, e6502_Address adr) {
  255. e6502_push8(core, core->registers.A);
  256. }
  257. static inline void php(e6502_Core *core, e6502_Address adr) {
  258. e6502_push8(core, core->registers.P |
  259. e6502_Status_1 |
  260. e6502_Status_B);
  261. }
  262. static inline void pla(e6502_Core *core, e6502_Address adr) {
  263. core->registers.A = e6502_pop8(core);
  264. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  265. if (!core->registers.A) core->registers.P |= e6502_Status_Z;
  266. core->registers.P |= (core->registers.A & e6502_Status_N);
  267. }
  268. static inline void plp(e6502_Core *core, e6502_Address adr) {
  269. core->registers.P = (e6502_pop8(core) |
  270. e6502_Status_1 |
  271. e6502_Status_B);
  272. }
  273. static inline void b(e6502_Core *core, e6502_Address adr) {
  274. uint8_t old_page = core->registers.PC >> 8;
  275. uint16_t new_addr = e6502_adr_mem(core, adr);
  276. if (old_page != (new_addr >> 8)) core->cycle++;
  277. core->registers.PC = new_addr;
  278. core->cycle++;
  279. }
  280. static inline void bpl(e6502_Core *core, e6502_Address adr) {
  281. if (!(core->registers.P & e6502_Status_N)) {
  282. b(core, adr);
  283. }
  284. }
  285. static inline void bmi(e6502_Core *core, e6502_Address adr) {
  286. if (core->registers.P & e6502_Status_N) {
  287. b(core, adr);
  288. }
  289. }
  290. static inline void bcc(e6502_Core *core, e6502_Address adr) {
  291. if (!(core->registers.P & e6502_Status_C)) {
  292. b(core, adr);
  293. }
  294. }
  295. static inline void bcs(e6502_Core *core, e6502_Address adr) {
  296. if (core->registers.P & e6502_Status_C) {
  297. b(core, adr);
  298. }
  299. }
  300. static inline void bvc(e6502_Core *core, e6502_Address adr) {
  301. if (!(core->registers.P & e6502_Status_V)) {
  302. b(core, adr);
  303. }
  304. }
  305. static inline void bvs(e6502_Core *core, e6502_Address adr) {
  306. if (core->registers.P & e6502_Status_V) {
  307. b(core, adr);
  308. }
  309. }
  310. static inline void bne(e6502_Core *core, e6502_Address adr) {
  311. if (!(core->registers.P & e6502_Status_Z)) {
  312. b(core, adr);
  313. }
  314. }
  315. static inline void beq(e6502_Core *core, e6502_Address adr) {
  316. if (core->registers.P & e6502_Status_Z) {
  317. b(core, adr);
  318. }
  319. }
  320. static inline void clc(e6502_Core *core, e6502_Address adr) {
  321. core->registers.P &= ~e6502_Status_C;
  322. }
  323. static inline void cli(e6502_Core *core, e6502_Address adr) {
  324. core->registers.P &= ~e6502_Status_I;
  325. }
  326. static inline void cld(e6502_Core *core, e6502_Address adr) {
  327. core->registers.P &= ~e6502_Status_D;
  328. }
  329. static inline void clv(e6502_Core *core, e6502_Address adr) {
  330. core->registers.P &= ~e6502_Status_V;
  331. }
  332. static inline void sec(e6502_Core *core, e6502_Address adr) {
  333. core->registers.P |= e6502_Status_C;
  334. }
  335. static inline void sei(e6502_Core *core, e6502_Address adr) {
  336. core->registers.P |= e6502_Status_I;
  337. }
  338. static inline void sed(e6502_Core *core, e6502_Address adr) {
  339. core->registers.P |= e6502_Status_D;
  340. }
  341. static inline void jsr(e6502_Core *core, e6502_Address adr) {
  342. e6502_push16(core, core->registers.PC - 1);
  343. core->registers.PC = e6502_adr_mem(core, adr);
  344. }
  345. static inline void jmp(e6502_Core *core, e6502_Address adr) {
  346. core->registers.PC = e6502_adr_mem(core, adr);
  347. }
  348. static inline void rts(e6502_Core *core, e6502_Address adr) {
  349. core->registers.PC = e6502_pop16(core) + 1;
  350. }
  351. static inline void bit(e6502_Core *core, e6502_Address adr) {
  352. uint8_t val = e6502_adr_r8(core, adr);
  353. core->registers.P &= ~(e6502_Status_Z |
  354. e6502_Status_V |
  355. e6502_Status_N);
  356. core->registers.P |= (val & (e6502_Status_V |
  357. e6502_Status_N));
  358. if (!(val & core->registers.A)) {
  359. core->registers.P |= e6502_Status_Z;
  360. }
  361. }
  362. static inline void cmp(e6502_Core *core,
  363. e6502_Address adr,
  364. uint8_t minuend) {
  365. uint8_t val = e6502_adr_r8(core, adr);
  366. uint8_t diff = minuend - val;
  367. core->registers.P &= ~(e6502_Status_C |
  368. e6502_Status_Z |
  369. e6502_Status_N);
  370. if (minuend >= val) core->registers.P |= e6502_Status_C;
  371. if (diff == 0) core->registers.P |= e6502_Status_Z;
  372. core->registers.P |= (diff & e6502_Status_N);
  373. }
  374. static inline void cpa(e6502_Core *core, e6502_Address adr) {
  375. cmp(core, adr, core->registers.A);
  376. }
  377. static inline void cpx(e6502_Core *core, e6502_Address adr) {
  378. cmp(core, adr, core->registers.X);
  379. }
  380. static inline void cpy(e6502_Core *core, e6502_Address adr) {
  381. cmp(core, adr, core->registers.Y);
  382. }
  383. static inline void and(e6502_Core *core, e6502_Address adr) {
  384. core->registers.A &= e6502_adr_r8(core, adr);
  385. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  386. core->registers.P |= (core->registers.A & e6502_Status_N);
  387. if (!core->registers.A) core->registers.P |= e6502_Status_Z;
  388. }
  389. static inline void adc(e6502_Core *core, e6502_Address adr) {
  390. uint8_t addend = e6502_adr_r8(core, adr);
  391. uint32_t sum = core->registers.A +
  392. addend +
  393. (core->registers.P & e6502_Status_C);
  394. core->registers.P &= ~(e6502_Status_C | e6502_Status_Z |
  395. e6502_Status_V | e6502_Status_N);
  396. if (sum > 0xFF) core->registers.P |= e6502_Status_C;
  397. if (!(uint8_t)sum) core->registers.P |= e6502_Status_Z;
  398. if ( (addend & 0x80) == (core->registers.A & 0x80) &&
  399. (sum & 0x80) != (addend & 0x80)) {
  400. core->registers.P |= e6502_Status_V;
  401. }
  402. core->registers.P |= (sum & e6502_Status_N);
  403. core->registers.A = sum;
  404. }
  405. static inline void sbc(e6502_Core *core, e6502_Address adr) {
  406. uint8_t addend = e6502_adr_r8(core, adr);
  407. uint32_t sum = core->registers.A -
  408. addend -
  409. (1 - (core->registers.P & e6502_Status_C));
  410. core->registers.P &= ~(e6502_Status_C | e6502_Status_Z |
  411. e6502_Status_V | e6502_Status_N);
  412. if (sum < 0x100) core->registers.P |= e6502_Status_C;
  413. if (!(uint8_t)sum) core->registers.P |= e6502_Status_Z;
  414. if ( (sum & 0x80) != (core->registers.A & 0x80) &&
  415. (addend & 0x80) != (core->registers.A & 0x80)) {
  416. core->registers.P |= e6502_Status_V;
  417. }
  418. core->registers.P |= (sum & e6502_Status_N);
  419. core->registers.A = sum;
  420. }
  421. static inline void inc(e6502_Core *core, e6502_Address adr) {
  422. // TODO: Emulate double-read or double-write
  423. uint8_t val = e6502_adr_r8(core, adr);
  424. e6502_adr_w8(core, adr, val);
  425. val += 1;
  426. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  427. core->registers.P |= (val & e6502_Status_N);
  428. if (!val) core->registers.P |= e6502_Status_Z;
  429. e6502_adr_w8(core, adr, val);
  430. }
  431. static inline void ini(e6502_Core *core, uint8_t* reg) {
  432. uint8_t val = *reg + 1;
  433. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  434. core->registers.P |= (val & e6502_Status_N);
  435. if (!val) core->registers.P |= e6502_Status_Z;
  436. *reg = val;
  437. }
  438. static inline void inx(e6502_Core *core, e6502_Address adr) {
  439. ini(core, &core->registers.X);
  440. }
  441. static inline void iny(e6502_Core *core, e6502_Address adr) {
  442. ini(core, &core->registers.Y);
  443. }
  444. static inline void dec(e6502_Core *core, e6502_Address adr) {
  445. // TODO: Emulate double-read or double-write
  446. uint8_t val = e6502_adr_r8(core, adr) - 1;
  447. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  448. core->registers.P |= (val & e6502_Status_N);
  449. if (!val) core->registers.P |= e6502_Status_Z;
  450. e6502_adr_w8(core, adr, val);
  451. }
  452. static inline void dei(e6502_Core *core, uint8_t* reg) {
  453. uint8_t val = *reg - 1;
  454. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  455. core->registers.P |= (val & e6502_Status_N);
  456. if (!val) core->registers.P |= e6502_Status_Z;
  457. *reg = val;
  458. }
  459. static inline void dex(e6502_Core *core, e6502_Address adr) {
  460. return dei(core, &core->registers.X);
  461. }
  462. static inline void dey(e6502_Core *core, e6502_Address adr) {
  463. return dei(core, &core->registers.Y);
  464. }
  465. static inline void sta(e6502_Core *core, e6502_Address adr) {
  466. e6502_adr_w8(core, adr, core->registers.A);
  467. }
  468. static inline void stx(e6502_Core *core, e6502_Address adr) {
  469. e6502_adr_w8(core, adr, core->registers.X);
  470. }
  471. static inline void sty(e6502_Core *core, e6502_Address adr) {
  472. e6502_adr_w8(core, adr, core->registers.Y);
  473. }
  474. static inline void t(e6502_Core *core,
  475. uint8_t* reg,
  476. uint8_t val) {
  477. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  478. core->registers.P |= (val & e6502_Status_N);
  479. if (!val) core->registers.P |= e6502_Status_Z;
  480. *reg = val;
  481. }
  482. static inline void tax(e6502_Core *core, e6502_Address adr) {
  483. t(core, &core->registers.X, core->registers.A);
  484. }
  485. static inline void tay(e6502_Core *core, e6502_Address adr) {
  486. t(core, &core->registers.Y, core->registers.A);
  487. }
  488. static inline void txs(e6502_Core *core, e6502_Address adr) {
  489. core->registers.S = core->registers.X;
  490. }
  491. static inline void txa(e6502_Core *core, e6502_Address adr) {
  492. t(core, &core->registers.A, core->registers.X);
  493. }
  494. static inline void tya(e6502_Core *core, e6502_Address adr) {
  495. t(core, &core->registers.A, core->registers.Y);
  496. }
  497. static inline void tsx(e6502_Core *core, e6502_Address adr) {
  498. t(core, &core->registers.X, core->registers.S);
  499. }
  500. static inline void lda(e6502_Core *core, e6502_Address adr) {
  501. t(core, &core->registers.A, e6502_adr_r8(core, adr));
  502. }
  503. static inline void ldx(e6502_Core *core, e6502_Address adr) {
  504. t(core, &core->registers.X, e6502_adr_r8(core, adr));
  505. }
  506. static inline void ldy(e6502_Core *core, e6502_Address adr) {
  507. t(core, &core->registers.Y, e6502_adr_r8(core, adr));
  508. }
  509. typedef struct {
  510. void(*operator)(e6502_Core*, e6502_Address);
  511. e6502_Address(*address)(e6502_Core*);
  512. uint16_t cycles;
  513. } e6502_Instruction;
  514. static const e6502_Instruction e6502_instructions[256] = {
  515. // 0x00
  516. [0b00000000] = {brk, adr_imp, 7},
  517. [0b00000001] = {ora, adr_ind_x, 6},
  518. [0b00000101] = {ora, adr_zp, 3},
  519. [0b00001001] = {ora, adr_imm, 2},
  520. [0b00001101] = {ora, adr_abs, 4},
  521. [0b00000110] = {asl, adr_zp, 5},
  522. [0b00001010] = {asl_a, adr_acc, 2},
  523. [0b00001110] = {asl, adr_abs, 6},
  524. [0b00001000] = {php, adr_imp, 3},
  525. // 0x10
  526. [0b00010000] = {bpl, adr_rel, 2},
  527. [0b00010001] = {ora, adr_ind_y, 5},
  528. [0b00010101] = {ora, adr_zp_x, 4},
  529. [0b00011001] = {ora, adr_abs_y, 4},
  530. [0b00011101] = {ora, adr_abs_x, 4},
  531. [0b00011000] = {clc, adr_imp, 2},
  532. [0b00010110] = {asl, adr_zp_x, 6},
  533. [0b00011110] = {asl, adr_abs_x, 7},
  534. // 0x20
  535. [0b00100000] = {jsr, adr_abs, 6},
  536. [0b00100100] = {bit, adr_zp, 3},
  537. [0b00101100] = {bit, adr_abs, 4},
  538. [0b00100001] = {and, adr_ind_x, 6},
  539. [0b00100101] = {and, adr_zp, 3},
  540. [0b00101001] = {and, adr_imm, 2},
  541. [0b00101101] = {and, adr_abs, 4},
  542. [0b00100110] = {rol, adr_zp, 5},
  543. [0b00101010] = {rol_a, adr_acc, 2},
  544. [0b00101110] = {rol, adr_abs, 6},
  545. [0b00101000] = {plp, adr_imp, 4},
  546. // 0x30
  547. [0b00110000] = {bmi, adr_rel, 2},
  548. [0b00110001] = {and, adr_ind_y, 5},
  549. [0b00110101] = {and, adr_zp_x, 4},
  550. [0b00111001] = {and, adr_abs_y, 3},
  551. [0b00111101] = {and, adr_abs_x, 3},
  552. [0b00110110] = {rol, adr_zp_x, 6},
  553. [0b00111110] = {rol, adr_abs_x, 7},
  554. [0b00111000] = {sec, adr_imp, 2},
  555. // 0x40
  556. [0b01000000] = {rti, adr_imp, 6},
  557. [0b01000001] = {eor, adr_ind_x, 6},
  558. [0b01000101] = {eor, adr_zp, 3},
  559. [0b01001001] = {eor, adr_imm, 2},
  560. [0b01001101] = {eor, adr_abs, 4},
  561. [0b01000110] = {lsr, adr_zp, 5},
  562. [0b01001010] = {lsr_a, adr_acc, 2},
  563. [0b01001110] = {lsr, adr_abs, 6},
  564. [0b01001000] = {pha, adr_imp, 3},
  565. [0b01001100] = {jmp, adr_abs, 3},
  566. // 0x50
  567. [0b01010000] = {bvc, adr_rel, 2},
  568. [0b01010001] = {eor, adr_ind_y, 5},
  569. [0b01010101] = {eor, adr_zp_x, 4},
  570. [0b01011001] = {eor, adr_abs_y, 4},
  571. [0b01011101] = {eor, adr_abs_x, 4},
  572. [0b01010110] = {lsr, adr_zp_x, 6},
  573. [0b01011110] = {lsr, adr_abs_x, 7},
  574. [0b01011000] = {cli, adr_imp, 2},
  575. // 0x60
  576. [0b01100000] = {rts, adr_imp, 6},
  577. [0b01100001] = {adc, adr_ind_x, 6},
  578. [0b01100101] = {adc, adr_zp, 3},
  579. [0b01101001] = {adc, adr_imm, 2},
  580. [0b01101101] = {adc, adr_abs, 4},
  581. [0b01100110] = {ror, adr_zp, 5},
  582. [0b01101010] = {ror_a, adr_acc, 2},
  583. [0b01101110] = {ror, adr_abs, 6},
  584. [0b01101000] = {pla, adr_imp, 4},
  585. [0b01101100] = {jmp, adr_ind, 5},
  586. // 0x70
  587. [0b01110000] = {bvs, adr_rel, 2},
  588. [0b01110001] = {adc, adr_ind_y, 5},
  589. [0b01110101] = {adc, adr_zp_x, 4},
  590. [0b01111001] = {adc, adr_abs_y, 4},
  591. [0b01111101] = {adc, adr_abs_x, 4},
  592. [0b01110110] = {ror, adr_zp_x, 6},
  593. [0b01111110] = {ror, adr_abs_x, 7},
  594. [0b01111000] = {sei, adr_imp, 2},
  595. // 0x80
  596. [0b10000001] = {sta, adr_ind_x, 6},
  597. [0b10000101] = {sta, adr_zp, 3},
  598. [0b10001101] = {sta, adr_abs, 4},
  599. [0b10000110] = {stx, adr_zp, 3},
  600. [0b10001110] = {stx, adr_abs, 4},
  601. [0b10000100] = {sty, adr_zp, 3},
  602. [0b10001100] = {sty, adr_abs, 4},
  603. [0b10001000] = {dey, adr_imp, 2},
  604. [0b10001010] = {txa, adr_imp, 2},
  605. // 0x90
  606. [0b10010000] = {bcc, adr_rel, 2},
  607. [0b10010001] = {sta, adr_ind_y, 6},
  608. [0b10010101] = {sta, adr_zp_x, 4},
  609. [0b10011001] = {sta, adr_abs_y, 5},
  610. [0b10011101] = {sta, adr_abs_x, 5},
  611. [0b10010110] = {stx, adr_zp_y, 4},
  612. [0b10010100] = {sty, adr_zp_x, 4},
  613. [0b10011000] = {tya, adr_imp, 2},
  614. [0b10011010] = {txs, adr_imp, 2},
  615. // 0xA0
  616. [0b10100001] = {lda, adr_ind_x, 6},
  617. [0b10100101] = {lda, adr_zp, 3},
  618. [0b10101001] = {lda, adr_imm, 2},
  619. [0b10101101] = {lda, adr_abs, 4},
  620. [0b10100010] = {ldx, adr_imm, 2},
  621. [0b10100110] = {ldx, adr_zp, 3},
  622. [0b10101110] = {ldx, adr_abs, 4},
  623. [0b10100000] = {ldy, adr_imm, 2},
  624. [0b10100100] = {ldy, adr_zp, 3},
  625. [0b10101100] = {ldy, adr_abs, 4},
  626. [0b10101010] = {tax, adr_imp, 2},
  627. [0b10101000] = {tay, adr_imp, 2},
  628. // 0xB0
  629. [0b10110000] = {bcs, adr_rel, 2},
  630. [0b10110001] = {lda, adr_ind_y, 5},
  631. [0b10110101] = {lda, adr_zp_x, 4},
  632. [0b10111001] = {lda, adr_abs_y, 4},
  633. [0b10111101] = {lda, adr_abs_x, 4},
  634. [0b10110110] = {ldx, adr_zp_y, 4},
  635. [0b10111110] = {ldx, adr_abs_y, 4},
  636. [0b10110100] = {ldy, adr_zp_x, 4},
  637. [0b10111100] = {ldy, adr_abs_x, 4},
  638. [0b10111000] = {clv, adr_imp, 2},
  639. [0b10111010] = {tsx, adr_imp, 2},
  640. // 0xC0
  641. [0b11000000] = {cpy, adr_imm, 2},
  642. [0b11000100] = {cpy, adr_zp, 3},
  643. [0b11001100] = {cpy, adr_abs, 4},
  644. [0b11000001] = {cpa, adr_ind_x, 6},
  645. [0b11000101] = {cpa, adr_zp, 3},
  646. [0b11001001] = {cpa, adr_imm, 2},
  647. [0b11001101] = {cpa, adr_abs, 4},
  648. [0b11001000] = {iny, adr_imp, 2},
  649. [0b11000110] = {dec, adr_zp, 5},
  650. [0b11001110] = {dec, adr_abs, 6},
  651. [0b11010110] = {dec, adr_zp_x, 6},
  652. [0b11011110] = {dec, adr_abs_x, 7},
  653. [0b11001010] = {dex, adr_imp, 2},
  654. // 0xD0
  655. [0b11010000] = {bne, adr_rel, 2},
  656. [0b11011000] = {cld, adr_imp, 2},
  657. [0b11010001] = {cpa, adr_ind_y, 5},
  658. [0b11010101] = {cpa, adr_zp_x, 4},
  659. [0b11011001] = {cpa, adr_abs_y, 4},
  660. [0b11011101] = {cpa, adr_abs_x, 4},
  661. // 0xE0
  662. [0b11100000] = {cpx, adr_imm, 2},
  663. [0b11100100] = {cpx, adr_zp, 3},
  664. [0b11101100] = {cpx, adr_abs, 4},
  665. [0b11100001] = {sbc, adr_ind_x, 6},
  666. [0b11100101] = {sbc, adr_zp, 3},
  667. [0b11101001] = {sbc, adr_imm, 2},
  668. [0b11101101] = {sbc, adr_abs, 4},
  669. [0b11100110] = {inc, adr_zp, 5},
  670. [0b11101110] = {inc, adr_abs, 6},
  671. [0b11101000] = {inx, adr_imp, 2},
  672. [0b11101010] = {nop, adr_imp, 2},
  673. // 0xF0
  674. [0b11110000] = {beq, adr_rel, 2},
  675. [0b11110001] = {sbc, adr_ind_y, 5},
  676. [0b11110101] = {sbc, adr_zp_x, 4},
  677. [0b11111001] = {sbc, adr_abs_y, 4},
  678. [0b11111101] = {sbc, adr_abs_x, 4},
  679. [0b11110110] = {inc, adr_zp_x, 6},
  680. [0b11111110] = {inc, adr_abs_x, 7},
  681. [0b11111000] = {sed, adr_imp, 2},
  682. };
  683. #ifdef E6502_DEBUG
  684. int e6502_instr_size(uint8_t opcode) {
  685. const e6502_Instruction* instr = &e6502_instructions[opcode];
  686. if ( instr->address == adr_imp ||
  687. instr->address == adr_acc) {
  688. return 1;
  689. } else if ( instr->address == adr_abs ||
  690. instr->address == adr_abs_x ||
  691. instr->address == adr_abs_y) {
  692. return 3;
  693. } else {
  694. return 2;
  695. }
  696. }
  697. void e6502_dump_instr(e6502_Core* core, e6502_Mem_Addr addr,
  698. FILE* file) {
  699. uint8_t opcode = e6502_r8(core, addr);
  700. int size = e6502_instr_size(opcode);
  701. fprintf(file, "$%02x", opcode);
  702. if (size == 2) {
  703. fprintf(file, " $%02x", e6502_r8(core, addr + 1));
  704. } else if (size == 3) {
  705. fprintf(file, " $%04x", e6502_r16(core, addr + 1));
  706. }
  707. // fputc('\n', file);
  708. }
  709. void e6502_dump_regs(e6502_Core* core, FILE* file) {
  710. fprintf(file, "S:%02x A:%02x X:%02x Y:%02x P:%02x\n",
  711. core->registers.S, core->registers.A,
  712. core->registers.X, core->registers.Y,
  713. core->registers.P);
  714. }
  715. #endif
  716. static void e6502_irq(e6502_Core* core) {
  717. if (!(core->registers.P & e6502_Status_I)) {
  718. e6502_push16(core, core->registers.PC);
  719. e6502_push8(core, (core->registers.P & ~e6502_Status_B) |
  720. e6502_Status_1);
  721. core->registers.P |= e6502_Status_I;
  722. core->registers.PC = e6502_r16(core, e6502_IRQ_Vec);
  723. }
  724. }
  725. static void e6502_nmi(e6502_Core* core) {
  726. e6502_push16(core, core->registers.PC);
  727. e6502_push8(core, (core->registers.P & ~e6502_Status_B) |
  728. e6502_Status_1);
  729. core->registers.P |= e6502_Status_I;
  730. core->registers.PC = e6502_r16(core, e6502_NMI_Vec);
  731. }
  732. int e6502_step(e6502_Core* core) {
  733. core->cycle = 0;
  734. #ifdef E6502_DEBUG
  735. int last_pc = core->registers.PC;
  736. #endif
  737. uint8_t opcode = e6502_r8(core, core->registers.PC);
  738. const e6502_Instruction* instr =
  739. &e6502_instructions[opcode];
  740. if (!instr->operator) {
  741. #ifdef E6502_DEBUG
  742. fprintf(stdout, "$%04x: $%02x -> ILLEGAL\n", last_pc, opcode);
  743. #endif
  744. #ifndef E6502_ILLEGAL
  745. core->cycle = -1;
  746. #else
  747. core->registers.PC++;
  748. core->cycle += 1;
  749. #endif
  750. } else {
  751. core->registers.PC++;
  752. e6502_Address adr = instr->address(core);
  753. #ifdef E6502_DEBUG
  754. uint16_t size = core->registers.PC - last_pc;
  755. uint16_t val = 0;
  756. if (size > 1) {
  757. if (size == 2) val = e6502_r8(core, last_pc + 1);
  758. else val = e6502_r16(core, last_pc + 1);
  759. }
  760. e6502_dump_regs(core, stdout);
  761. fprintf(stdout, "$%04x: ", last_pc);
  762. e6502_dump_instr(core, last_pc, stdout);
  763. fputs(" -> ", stdout);
  764. e6502_fprintf_instr(stdout, opcode, (uint8_t*)&val);
  765. fputc('\n', stdout);
  766. #endif
  767. instr->operator(core, adr);
  768. core->cycle += instr->cycles;
  769. if ( (core->pins & e6502_Pin_NMI) &&
  770. !(core->pins & e6502_NMI_Serviced)) {
  771. core->pins |= e6502_NMI_Serviced;
  772. e6502_nmi(core);
  773. } else if ( (core->pins & e6502_Pin_IRQ) &&
  774. !(core->registers.P & e6502_Status_I)) {
  775. e6502_irq(core);
  776. }
  777. }
  778. return core->cycle;
  779. }
  780. int e6502_run(e6502_Core* core,
  781. int remaining,
  782. int* run,
  783. int instructions) {
  784. int status = 0;
  785. int count = 0;
  786. int last_pc = -1;
  787. (void)last_pc;
  788. while (count < remaining) {
  789. #ifdef E6502_HCF
  790. if (core->registers.PC == last_pc) {
  791. // Trapped.
  792. status = -2;
  793. break;
  794. }
  795. #endif
  796. last_pc = core->registers.PC;
  797. int cpu_cycles = e6502_step(core);
  798. if (cpu_cycles <= 0) {
  799. status = cpu_cycles;
  800. break;
  801. }
  802. count += (instructions ? 1 : cpu_cycles);
  803. }
  804. if (run) {
  805. *run = count;
  806. }
  807. return status;
  808. }
  809. #ifdef E6502_POLL_MEM
  810. void e6502_init(e6502_Core* core) { /* nuthin' */ }
  811. #else
  812. void e6502_init(e6502_Core* core, e6502_Read read,
  813. e6502_Write write, void* context) {
  814. core->bus_read = read;
  815. core->bus_write = write;
  816. core->bus_context = context;
  817. }
  818. #endif
  819. void e6502_reset(e6502_Core* core) {
  820. core->registers.PC = e6502_r16(core, e6502_Reset_Vec);
  821. core->registers.S -= 3;
  822. core->registers.P |= (e6502_Status_B | e6502_Status_1);
  823. }
  824. void e6502_set_nmi(e6502_Core* core, int active) {
  825. if (active) core->pins |= e6502_Pin_NMI;
  826. else core->pins &= ~(e6502_Pin_NMI | e6502_NMI_Serviced);
  827. }
  828. void e6502_set_irq(e6502_Core* core, int active) {
  829. if (active) core->pins |= e6502_Pin_IRQ;
  830. else core->pins &= ~e6502_Pin_IRQ;
  831. }