A MOS 6502 emulator written in C with a focus on speed, especially for ARM targets.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

1019 lines
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. }