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.

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