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.

843 lignes
24KB

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