A MOS 6502 emulator written in C with a focus on speed, especially for ARM targets.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

932 linhas
27KB

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