A MOS 6502 emulator written in C with a focus on speed, especially for ARM targets.
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

1008 líneas
29KB

  1. #include "e6502.h"
  2. #ifdef E6502_DEBUG
  3. #include <stdio.h>
  4. #endif
  5. // Instruction Addressing
  6. #ifdef E6502_POLL_MEM
  7. typedef uint8_t* e6502_Address;
  8. static inline e6502_Address e6502_mem_adr(e6502_Core* core,
  9. e6502_Mem_Addr adr) {
  10. return &core->memory[adr];
  11. }
  12. static inline e6502_Mem_Addr e6502_adr_mem(e6502_Core* core,
  13. e6502_Address adr) {
  14. return (adr - core->memory);
  15. }
  16. static inline uint8_t e6502_adr_r8(e6502_Core* core,
  17. e6502_Address adr) {
  18. return &adr[0];
  19. }
  20. static inline uint8_t e6502_adr_r16(e6502_Core* core,
  21. e6502_Address adr) {
  22. return (&adr[0] | ((uint16_t)&adr[1] << 8));
  23. }
  24. static inline void e6502_adr_w8(e6502_Core* core,
  25. e6502_Address adr,
  26. uint8_t val) {
  27. &adr[0] = val;
  28. }
  29. static inline void e6502_adr_w16(e6502_Core* core,
  30. e6502_Address adr,
  31. uint16_t val) {
  32. &adr[0] = val;
  33. &adr[1] = val >> 8;
  34. }
  35. #else // !E6502_POLL_MEM
  36. typedef uint16_t e6502_Address;
  37. static inline e6502_Address e6502_mem_adr(e6502_Core*,
  38. e6502_Mem_Addr adr) {
  39. return adr;
  40. }
  41. static inline e6502_Mem_Addr e6502_adr_mem(e6502_Core*,
  42. e6502_Address adr) {
  43. return adr;
  44. }
  45. static inline uint8_t e6502_adr_r8(e6502_Core* core,
  46. e6502_Address adr) {
  47. return e6502_r8(core, adr);
  48. }
  49. static inline uint8_t e6502_adr_r16(e6502_Core* core,
  50. e6502_Address adr) {
  51. return e6502_r16(core, adr);
  52. }
  53. static inline void e6502_adr_w8(e6502_Core* core,
  54. e6502_Address adr,
  55. uint8_t val) {
  56. e6502_w8(core, adr, val);
  57. }
  58. static inline void e6502_adr_w16(e6502_Core* core,
  59. e6502_Address adr,
  60. uint16_t val) {
  61. e6502_w16(core, adr,val);
  62. }
  63. #endif // !E6502_POLL_MEM
  64. // Read values after opcodes
  65. static inline uint8_t arg8(e6502_Core* core) {
  66. return e6502_r8(core, core->registers.PC++);
  67. }
  68. static inline uint16_t arg16(e6502_Core* core) {
  69. return (arg8(core) | ((uint16_t)arg8(core) << 8));
  70. }
  71. // Interpret opcode values
  72. static inline e6502_Address adr_imp(e6502_Core*) {
  73. return 0;
  74. }
  75. static inline e6502_Address adr_acc(e6502_Core* core) {
  76. return 0;
  77. }
  78. static inline e6502_Address adr_ind(e6502_Core* core) {
  79. return e6502_mem_adr(core, e6502_r16(core, arg16(core)));
  80. }
  81. static inline e6502_Address adr_ind_x(e6502_Core* core) {
  82. return e6502_mem_adr(core, e6502_r16(
  83. core,
  84. (uint8_t)(core->registers.X + arg8(core))
  85. ));
  86. }
  87. static inline e6502_Address adr_ind_y(e6502_Core* core) {
  88. uint16_t zp_adr = e6502_r16(core, arg8(core));
  89. uint8_t old_page = zp_adr >> 8;
  90. uint16_t new_adr = core->registers.Y + zp_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_i(e6502_Core* core,
  95. uint8_t i) {
  96. uint16_t abs_adr = arg16(core);
  97. uint8_t old_page = abs_adr >> 8;
  98. uint16_t new_adr = i + abs_adr;
  99. if (new_adr >> 8 != old_page) core->cycle++;
  100. return e6502_mem_adr(core, new_adr);
  101. }
  102. static inline e6502_Address adr_abs_x(e6502_Core* core) {
  103. return adr_abs_i(core, core->registers.X);
  104. }
  105. static inline e6502_Address adr_abs_y(e6502_Core* core) {
  106. return adr_abs_i(core, core->registers.Y);
  107. }
  108. static inline e6502_Address adr_zp(e6502_Core* core) {
  109. return e6502_mem_adr(core, arg8(core));
  110. }
  111. static inline e6502_Address adr_zp_x(e6502_Core* core) {
  112. return e6502_mem_adr(
  113. core, (uint8_t)(arg8(core) + core->registers.X)
  114. );
  115. }
  116. static inline e6502_Address adr_zp_y(e6502_Core* core) {
  117. return e6502_mem_adr(
  118. core, (uint8_t)(arg8(core) + core->registers.Y)
  119. );
  120. }
  121. static inline e6502_Address adr_abs(e6502_Core* core) {
  122. return e6502_mem_adr(core, arg16(core));
  123. }
  124. static inline e6502_Address adr_imm(e6502_Core* core) {
  125. return e6502_mem_adr(core, core->registers.PC++);
  126. }
  127. static inline e6502_Address adr_rel(e6502_Core* core) {
  128. return e6502_mem_adr(
  129. core, (int8_t)arg8(core) + core->registers.PC
  130. );
  131. }
  132. // Instructions
  133. static inline void nop(e6502_Core*, e6502_Address) {
  134. // NOP
  135. }
  136. static inline void brk(e6502_Core *core, e6502_Address) {
  137. e6502_push16(core, core->registers.PC + 1);
  138. e6502_push8(core, core->registers.P |
  139. e6502_Status_1 |
  140. e6502_Status_B);
  141. core->registers.P |= e6502_Status_I;
  142. core->registers.PC = e6502_r16(core, e6502_IRQ_Vec);
  143. }
  144. static inline void rti(e6502_Core *core, e6502_Address) {
  145. core->registers.P = e6502_pop8(core) |
  146. e6502_Status_1 |
  147. e6502_Status_B;
  148. core->registers.PC = e6502_pop16(core);
  149. }
  150. static inline void ora(e6502_Core *core, e6502_Address adr) {
  151. core->registers.A |= e6502_adr_r8(core, adr);
  152. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  153. core->registers.P |= (core->registers.A & e6502_Status_N);
  154. if (!core->registers.A) core->registers.P |= e6502_Status_Z;
  155. }
  156. static inline void eor(e6502_Core *core, e6502_Address adr) {
  157. core->registers.A ^= e6502_adr_r8(core, adr);
  158. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  159. core->registers.P |= (core->registers.A & e6502_Status_N);
  160. if (!core->registers.A) core->registers.P |= e6502_Status_Z;
  161. }
  162. static inline void asl(e6502_Core *core, e6502_Address adr) {
  163. uint8_t val = e6502_adr_r8(core, adr);
  164. core->registers.P &= ~(e6502_Status_C |
  165. e6502_Status_Z |
  166. e6502_Status_N);
  167. if (val & 0x80) core->registers.P |= e6502_Status_C;
  168. val <<= 1;
  169. core->registers.P |= (val & e6502_Status_N);
  170. if (!val) core->registers.P |= e6502_Status_Z;
  171. e6502_adr_w8(core, adr, val);
  172. }
  173. static inline void asl_a(e6502_Core *core, e6502_Address adr) {
  174. uint8_t val = core->registers.A;
  175. core->registers.P &= ~(e6502_Status_C |
  176. e6502_Status_Z |
  177. e6502_Status_N);
  178. if (val & 0x80) core->registers.P |= e6502_Status_C;
  179. val <<= 1;
  180. core->registers.P |= (val & e6502_Status_N);
  181. if (!val) core->registers.P |= e6502_Status_Z;
  182. core->registers.A = val;
  183. }
  184. static inline void lsr(e6502_Core *core, e6502_Address adr) {
  185. uint8_t val = e6502_adr_r8(core, adr);
  186. core->registers.P &= ~(e6502_Status_C |
  187. e6502_Status_Z |
  188. e6502_Status_N);
  189. core->registers.P |= (val & e6502_Status_C);
  190. val >>= 1;
  191. core->registers.P |= (val & e6502_Status_N);
  192. if (!val) core->registers.P |= e6502_Status_Z;
  193. e6502_adr_w8(core, adr, val);
  194. }
  195. static inline void lsr_a(e6502_Core *core, e6502_Address adr) {
  196. uint8_t val = core->registers.A;
  197. core->registers.P &= ~(e6502_Status_C |
  198. e6502_Status_Z |
  199. e6502_Status_N);
  200. core->registers.P |= (val & e6502_Status_C);
  201. val >>= 1;
  202. core->registers.P |= (val & e6502_Status_N);
  203. if (!val) core->registers.P |= e6502_Status_Z;
  204. core->registers.A = val;
  205. }
  206. static inline void rol(e6502_Core *core, e6502_Address adr) {
  207. uint8_t val = e6502_adr_r8(core, adr);
  208. uint8_t new_c = (val & 0x80) ? e6502_Status_C : 0;
  209. val <<= 1;
  210. val |= (core->registers.P & e6502_Status_C);
  211. core->registers.P &= ~(e6502_Status_C |
  212. e6502_Status_Z |
  213. e6502_Status_N);
  214. core->registers.P |= new_c;
  215. if (!val) core->registers.P |= e6502_Status_Z;
  216. core->registers.P |= (val & e6502_Status_N);
  217. e6502_adr_w8(core, adr, val);
  218. }
  219. static inline void rol_a(e6502_Core *core, e6502_Address adr) {
  220. uint8_t val = core->registers.A;
  221. uint8_t new_c = (val & 0x80) ? e6502_Status_C : 0;
  222. val <<= 1;
  223. val |= (core->registers.P & e6502_Status_C);
  224. core->registers.P &= ~(e6502_Status_C |
  225. e6502_Status_Z |
  226. e6502_Status_N);
  227. core->registers.P |= new_c;
  228. if (!val) core->registers.P |= e6502_Status_Z;
  229. core->registers.P |= (val & e6502_Status_N);
  230. core->registers.A = val;
  231. }
  232. static inline void ror(e6502_Core *core, e6502_Address adr) {
  233. uint8_t val = e6502_adr_r8(core, adr);
  234. uint8_t new_c = (val & e6502_Status_C);
  235. val >>= 1;
  236. if (core->registers.P & e6502_Status_C) val |= e6502_Status_N;
  237. core->registers.P &= ~(e6502_Status_C |
  238. e6502_Status_Z |
  239. e6502_Status_N);
  240. core->registers.P |= new_c;
  241. if (!val) core->registers.P |= e6502_Status_Z;
  242. core->registers.P |= (val & e6502_Status_N);
  243. e6502_adr_w8(core, adr, val);
  244. }
  245. static inline void ror_a(e6502_Core *core, e6502_Address adr) {
  246. uint8_t val = core->registers.A;
  247. uint8_t new_c = (val & e6502_Status_C);
  248. val >>= 1;
  249. if (core->registers.P & e6502_Status_C) val |= e6502_Status_N;
  250. core->registers.P &= ~(e6502_Status_C |
  251. e6502_Status_Z |
  252. e6502_Status_N);
  253. core->registers.P |= new_c;
  254. if (!val) core->registers.P |= e6502_Status_Z;
  255. core->registers.P |= (val & e6502_Status_N);
  256. core->registers.A = val;
  257. }
  258. static inline void pha(e6502_Core *core, e6502_Address adr) {
  259. e6502_push8(core, core->registers.A);
  260. }
  261. static inline void php(e6502_Core *core, e6502_Address adr) {
  262. e6502_push8(core, core->registers.P |
  263. e6502_Status_1 |
  264. e6502_Status_B);
  265. }
  266. static inline void pla(e6502_Core *core, e6502_Address adr) {
  267. core->registers.A = e6502_pop8(core);
  268. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  269. if (!core->registers.A) core->registers.P |= e6502_Status_Z;
  270. core->registers.P |= (core->registers.A & e6502_Status_N);
  271. }
  272. static inline void plp(e6502_Core *core, e6502_Address adr) {
  273. core->registers.P = (e6502_pop8(core) |
  274. e6502_Status_1 |
  275. e6502_Status_B);
  276. }
  277. static inline void b(e6502_Core *core, e6502_Address adr) {
  278. uint8_t old_page = core->registers.PC >> 8;
  279. uint16_t new_addr = e6502_adr_mem(core, adr);
  280. if (old_page != (new_addr >> 8)) core->cycle++;
  281. core->registers.PC = new_addr;
  282. core->cycle++;
  283. }
  284. static inline void bpl(e6502_Core *core, e6502_Address adr) {
  285. if (!(core->registers.P & e6502_Status_N)) {
  286. b(core, adr);
  287. }
  288. }
  289. static inline void bmi(e6502_Core *core, e6502_Address adr) {
  290. if (core->registers.P & e6502_Status_N) {
  291. b(core, adr);
  292. }
  293. }
  294. static inline void bcc(e6502_Core *core, e6502_Address adr) {
  295. if (!(core->registers.P & e6502_Status_C)) {
  296. b(core, adr);
  297. }
  298. }
  299. static inline void bcs(e6502_Core *core, e6502_Address adr) {
  300. if (core->registers.P & e6502_Status_C) {
  301. b(core, adr);
  302. }
  303. }
  304. static inline void bvc(e6502_Core *core, e6502_Address adr) {
  305. if (!(core->registers.P & e6502_Status_V)) {
  306. b(core, adr);
  307. }
  308. }
  309. static inline void bvs(e6502_Core *core, e6502_Address adr) {
  310. if (core->registers.P & e6502_Status_V) {
  311. b(core, adr);
  312. }
  313. }
  314. static inline void bne(e6502_Core *core, e6502_Address adr) {
  315. if (!(core->registers.P & e6502_Status_Z)) {
  316. b(core, adr);
  317. }
  318. }
  319. static inline void beq(e6502_Core *core, e6502_Address adr) {
  320. if (core->registers.P & e6502_Status_Z) {
  321. b(core, adr);
  322. }
  323. }
  324. static inline void clc(e6502_Core *core, e6502_Address) {
  325. core->registers.P &= ~e6502_Status_C;
  326. }
  327. static inline void cli(e6502_Core *core, e6502_Address) {
  328. core->registers.P &= ~e6502_Status_I;
  329. }
  330. static inline void cld(e6502_Core *core, e6502_Address) {
  331. core->registers.P &= ~e6502_Status_D;
  332. }
  333. static inline void clv(e6502_Core *core, e6502_Address) {
  334. core->registers.P &= ~e6502_Status_V;
  335. }
  336. static inline void sec(e6502_Core *core, e6502_Address) {
  337. core->registers.P |= e6502_Status_C;
  338. }
  339. static inline void sei(e6502_Core *core, e6502_Address) {
  340. core->registers.P |= e6502_Status_I;
  341. }
  342. static inline void sed(e6502_Core *core, e6502_Address) {
  343. core->registers.P |= e6502_Status_D;
  344. }
  345. static inline void jsr(e6502_Core *core, e6502_Address adr) {
  346. e6502_push16(core, core->registers.PC - 1);
  347. core->registers.PC = e6502_adr_mem(core, adr);
  348. }
  349. static inline void jmp(e6502_Core *core, e6502_Address adr) {
  350. core->registers.PC = e6502_adr_mem(core, adr);
  351. }
  352. static inline void rts(e6502_Core *core, e6502_Address) {
  353. core->registers.PC = e6502_pop16(core) + 1;
  354. }
  355. static inline void bit(e6502_Core *core, e6502_Address adr) {
  356. uint8_t val = e6502_adr_r8(core, adr);
  357. core->registers.P &= ~(e6502_Status_Z |
  358. e6502_Status_V |
  359. e6502_Status_N);
  360. core->registers.P |= (val & (e6502_Status_V |
  361. e6502_Status_N));
  362. if (!(val & core->registers.A)) {
  363. core->registers.P |= e6502_Status_Z;
  364. }
  365. }
  366. static inline void cmp(e6502_Core *core,
  367. e6502_Address adr,
  368. uint8_t minuend) {
  369. uint8_t val = e6502_adr_r8(core, adr);
  370. uint8_t diff = minuend - val;
  371. core->registers.P &= ~(e6502_Status_C |
  372. e6502_Status_Z |
  373. e6502_Status_N);
  374. if (minuend >= val) core->registers.P |= e6502_Status_C;
  375. if (diff == 0) core->registers.P |= e6502_Status_Z;
  376. core->registers.P |= (diff & e6502_Status_N);
  377. }
  378. static inline void cpa(e6502_Core *core, e6502_Address adr) {
  379. cmp(core, adr, core->registers.A);
  380. }
  381. static inline void cpx(e6502_Core *core, e6502_Address adr) {
  382. cmp(core, adr, core->registers.X);
  383. }
  384. static inline void cpy(e6502_Core *core, e6502_Address adr) {
  385. cmp(core, adr, core->registers.Y);
  386. }
  387. static inline void and(e6502_Core *core, e6502_Address adr) {
  388. core->registers.A &= e6502_adr_r8(core, adr);
  389. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  390. core->registers.P |= (core->registers.A & e6502_Status_N);
  391. if (!core->registers.A) core->registers.P |= e6502_Status_Z;
  392. }
  393. static inline void adc(e6502_Core *core, e6502_Address adr) {
  394. uint8_t addend = e6502_adr_r8(core, adr);
  395. uint32_t sum = core->registers.A +
  396. addend +
  397. (core->registers.P & e6502_Status_C);
  398. core->registers.P &= ~(e6502_Status_C | e6502_Status_Z |
  399. e6502_Status_V | e6502_Status_N);
  400. if (sum > 0xFF) core->registers.P |= e6502_Status_C;
  401. if (!(uint8_t)sum) core->registers.P |= e6502_Status_Z;
  402. if ( (addend & 0x80) == (core->registers.A & 0x80) &&
  403. (sum & 0x80) != (addend & 0x80)) {
  404. core->registers.P |= e6502_Status_V;
  405. }
  406. core->registers.P |= (sum & e6502_Status_N);
  407. core->registers.A = sum;
  408. }
  409. static inline void sbc(e6502_Core *core, e6502_Address adr) {
  410. uint8_t addend = e6502_adr_r8(core, adr);
  411. uint32_t sum = core->registers.A -
  412. addend -
  413. (1 - (core->registers.P & e6502_Status_C));
  414. core->registers.P &= ~(e6502_Status_C | e6502_Status_Z |
  415. e6502_Status_V | e6502_Status_N);
  416. if (sum < 0x100) core->registers.P |= e6502_Status_C;
  417. if (!(uint8_t)sum) core->registers.P |= e6502_Status_Z;
  418. if ( (sum & 0x80) != (core->registers.A & 0x80) &&
  419. (addend & 0x80) != (core->registers.A & 0x80)) {
  420. core->registers.P |= e6502_Status_V;
  421. }
  422. core->registers.P |= (sum & e6502_Status_N);
  423. core->registers.A = sum;
  424. }
  425. static inline void inc(e6502_Core *core, e6502_Address adr) {
  426. uint8_t val = e6502_adr_r8(core, adr) + 1;
  427. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  428. core->registers.P |= (val & e6502_Status_N);
  429. if (!val) core->registers.P |= e6502_Status_Z;
  430. e6502_adr_w8(core, adr, val);
  431. }
  432. static inline void ini(e6502_Core *core, uint8_t* reg) {
  433. uint8_t val = *reg + 1;
  434. core->registers.P &= ~(e6502_Status_Z | e6502_Status_N);
  435. core->registers.P |= (val & e6502_Status_N);
  436. if (!val) core->registers.P |= e6502_Status_Z;
  437. *reg = val;
  438. }
  439. static inline void inx(e6502_Core *core, e6502_Address) {
  440. ini(core, &core->registers.X);
  441. }
  442. static inline void iny(e6502_Core *core, e6502_Address) {
  443. ini(core, &core->registers.Y);
  444. }
  445. static inline void dec(e6502_Core *core, e6502_Address adr) {
  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) {
  460. return dei(core, &core->registers.X);
  461. }
  462. static inline void dey(e6502_Core *core, e6502_Address) {
  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) {
  483. t(core, &core->registers.X, core->registers.A);
  484. }
  485. static inline void tay(e6502_Core *core, e6502_Address) {
  486. t(core, &core->registers.Y, core->registers.A);
  487. }
  488. static inline void txs(e6502_Core *core, e6502_Address) {
  489. core->registers.S = core->registers.X;
  490. }
  491. static inline void txa(e6502_Core *core, e6502_Address) {
  492. t(core, &core->registers.A, core->registers.X);
  493. }
  494. static inline void tya(e6502_Core *core, e6502_Address) {
  495. t(core, &core->registers.A, core->registers.Y);
  496. }
  497. static inline void tsx(e6502_Core *core, e6502_Address) {
  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. /*
  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. int 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. */
  710. #ifdef E6502_DEBUG
  711. int e6502_dump_regs(e6502_Core* core, FILE* file) {
  712. fprintf(file, "S:%02x A:%02x X:%02x Y:%02x P:%02x\n",
  713. core->registers.S, core->registers.A,
  714. core->registers.X, core->registers.Y,
  715. core->registers.P);
  716. }
  717. #endif
  718. static void e6502_irq(e6502_Core* core) {
  719. if (!(core->registers.P & e6502_Status_I)) {
  720. e6502_push16(core, core->registers.PC);
  721. e6502_push8(core, (core->registers.P & ~e6502_Status_B) |
  722. e6502_Status_1);
  723. core->registers.P |= e6502_Status_I;
  724. core->registers.PC = e6502_r16(core, e6502_IRQ_Vec);
  725. }
  726. }
  727. static void e6502_nmi(e6502_Core* core) {
  728. e6502_push16(core, core->registers.PC);
  729. e6502_push8(core, (core->registers.P & ~e6502_Status_B) |
  730. e6502_Status_1);
  731. core->registers.P |= e6502_Status_I;
  732. core->registers.PC = e6502_r16(core, e6502_NMI_Vec);
  733. }
  734. int e6502_run(e6502_Core* core,
  735. int remaining,
  736. int* run,
  737. int instructions) {
  738. int status = 0;
  739. int i_count = 0;
  740. int start = (instructions ? i_count : core->cycle);
  741. int end = start + remaining;
  742. int last_pc = -1;
  743. while ((instructions ? i_count : core->cycle) < end) {
  744. if (core->registers.PC == last_pc) {
  745. // Trapped.
  746. status = -2;
  747. break;
  748. }
  749. last_pc = core->registers.PC;
  750. uint8_t opcode = e6502_r8(core, core->registers.PC);
  751. const e6502_Instruction* instr =
  752. &e6502_instructions[opcode];
  753. if (!instr->operator) {
  754. #ifdef E6502_DEBUG
  755. fprintf(stdout, "$%04x: %02x\n", last_pc, opcode);
  756. #endif
  757. status = -1;
  758. break;
  759. } else {
  760. core->registers.PC++;
  761. e6502_Address adr = instr->address(core);
  762. #ifdef E6502_DEBUG
  763. uint16_t size = core->registers.PC - last_pc;
  764. uint16_t val = 0;
  765. if (size > 1) {
  766. if (size == 2) val = e6502_r8(core, last_pc + 1);
  767. else val = e6502_r16(core, last_pc + 1);
  768. }
  769. e6502_dump_regs(core, stdout);
  770. fprintf(stdout, "$%04x: $%02x", last_pc, opcode);
  771. if (size > 1) {
  772. fprintf(stdout, size == 2 ? " $%02x" : " $%04x",
  773. val);
  774. }
  775. fputc('\n', stdout);
  776. #endif
  777. instr->operator(core, adr);
  778. core->cycle += instr->cycles;
  779. i_count++;
  780. if ( (core->pins & e6502_Pin_NMI) &&
  781. !(core->pins & e6502_NMI_Serviced)) {
  782. core->pins |= e6502_NMI_Serviced;
  783. e6502_nmi(core);
  784. } else if ( (core->pins & e6502_Pin_IRQ) &&
  785. !(core->registers.P & e6502_Status_I)) {
  786. e6502_irq(core);
  787. }
  788. }
  789. }
  790. if (run) {
  791. *run = (instructions ? i_count : core->cycle) - start;
  792. }
  793. return status;
  794. }
  795. void e6502_init(e6502_Core* core, e6502_Read read,
  796. e6502_Write write, void* context) {
  797. core->bus_read = read;
  798. core->bus_write = write;
  799. core->bus_context = context;
  800. }
  801. void e6502_reset(e6502_Core* core) {
  802. core->registers.PC = e6502_r16(core, e6502_Reset_Vec);
  803. core->registers.S -= 3;
  804. core->registers.P |= (e6502_Status_B | e6502_Status_1);
  805. }
  806. void e6502_set_nmi(e6502_Core* core, int active) {
  807. if (active) core->pins |= e6502_Pin_NMI;
  808. else core->pins &= ~(e6502_Pin_NMI | e6502_NMI_Serviced);
  809. }
  810. void e6502_set_irq(e6502_Core* core, int active) {
  811. if (active) core->pins |= e6502_Pin_IRQ;
  812. else core->pins &= ~e6502_Pin_IRQ;
  813. }