A MOS 6502 emulator written in C with a focus on speed, especially for ARM targets.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1021 lines
30KB

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