comparison z80_to_x86.c @ 593:5ef3fe516da9

Z80 core is sort of working again
author Michael Pavone <pavone@retrodev.com>
date Mon, 22 Dec 2014 20:55:10 -0800
parents 4ff7bbb3943b
children 086de8692932
comparison
equal deleted inserted replaced
592:4ff7bbb3943b 593:5ef3fe516da9
25 #ifdef DO_DEBUG_PRINT 25 #ifdef DO_DEBUG_PRINT
26 #define dprintf printf 26 #define dprintf printf
27 #else 27 #else
28 #define dprintf 28 #define dprintf
29 #endif 29 #endif
30
31 void z80_read_byte();
32 void z80_read_word();
33 void z80_write_byte();
34 void z80_write_word_highfirst();
35 void z80_write_word_lowfirst();
36 void z80_save_context();
37 void z80_native_addr();
38 void z80_do_sync();
39 void z80_handle_cycle_limit_int();
40 void z80_retrans_stub();
41 void z80_io_read();
42 void z80_io_write();
43 void z80_halt();
44 void z80_save_context();
45 void z80_load_context();
46 30
47 uint8_t z80_size(z80inst * inst) 31 uint8_t z80_size(z80inst * inst)
48 { 32 {
49 uint8_t reg = (inst->reg & 0x1F); 33 uint8_t reg = (inst->reg & 0x1F);
50 if (reg != Z80_UNUSED && reg != Z80_USE_IMMED) { 34 if (reg != Z80_UNUSED && reg != Z80_USE_IMMED) {
182 if (read) { 166 if (read) {
183 /*if (modify) { 167 /*if (modify) {
184 push_r(code, opts->gen.scratch1); 168 push_r(code, opts->gen.scratch1);
185 }*/ 169 }*/
186 if (size == SZ_B) { 170 if (size == SZ_B) {
187 call(code, (uint8_t *)z80_read_byte); 171 call(code, opts->read_8);
188 } else { 172 } else {
189 call(code, (uint8_t *)z80_read_word); 173 call(code, opts->read_16);
190 } 174 }
191 if (modify) { 175 if (modify) {
192 //pop_r(code, opts->gen.scratch2); 176 //pop_r(code, opts->gen.scratch2);
193 mov_ir(code, inst->immed, opts->gen.scratch2, SZ_W); 177 mov_ir(code, inst->immed, opts->gen.scratch2, SZ_W);
194 } 178 }
205 if (modify) { 189 if (modify) {
206 //push_r(code, opts->gen.scratch1); 190 //push_r(code, opts->gen.scratch1);
207 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_W); 191 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_W);
208 } 192 }
209 if (size == SZ_B) { 193 if (size == SZ_B) {
210 call(code, (uint8_t *)z80_read_byte); 194 call(code, opts->read_8);
211 } else { 195 } else {
212 call(code, (uint8_t *)z80_read_word); 196 call(code, opts->read_16);
213 } 197 }
214 if (modify) { 198 if (modify) {
215 //pop_r(code, opts->gen.scratch2); 199 //pop_r(code, opts->gen.scratch2);
216 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W); 200 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W);
217 } 201 }
246 } 230 }
247 } 231 }
248 } 232 }
249 } 233 }
250 234
251 void z80_save_result(code_info *code, z80inst * inst) 235 void z80_save_result(z80_options *opts, z80inst * inst)
252 { 236 {
253 switch(inst->addr_mode & 0x1f) 237 switch(inst->addr_mode & 0x1f)
254 { 238 {
255 case Z80_REG_INDIRECT: 239 case Z80_REG_INDIRECT:
256 case Z80_IMMED_INDIRECT: 240 case Z80_IMMED_INDIRECT:
257 case Z80_IX_DISPLACE: 241 case Z80_IX_DISPLACE:
258 case Z80_IY_DISPLACE: 242 case Z80_IY_DISPLACE:
259 if (z80_size(inst) == SZ_B) { 243 if (z80_size(inst) == SZ_B) {
260 call(code, (uint8_t *)z80_write_byte); 244 call(&opts->gen.code, opts->write_8);
261 } else { 245 } else {
262 call(code, (uint8_t *)z80_write_word_lowfirst); 246 call(&opts->gen.code, opts->write_16_lowfirst);
263 } 247 }
264 } 248 }
265 } 249 }
266 250
267 enum { 251 enum {
367 mov_rdispr(code, src_op.base, src_op.disp, dst_op.base, size); 351 mov_rdispr(code, src_op.base, src_op.disp, dst_op.base, size);
368 } 352 }
369 z80_save_reg(inst, opts); 353 z80_save_reg(inst, opts);
370 z80_save_ea(code, inst, opts); 354 z80_save_ea(code, inst, opts);
371 if (inst->addr_mode & Z80_DIR) { 355 if (inst->addr_mode & Z80_DIR) {
372 z80_save_result(code, inst); 356 z80_save_result(opts, inst);
373 } 357 }
374 break; 358 break;
375 case Z80_PUSH: 359 case Z80_PUSH:
376 cycles(&opts->gen, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 9 : 5); 360 cycles(&opts->gen, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 9 : 5);
377 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); 361 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
392 } else { 376 } else {
393 translate_z80_reg(inst, &src_op, opts); 377 translate_z80_reg(inst, &src_op, opts);
394 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_W); 378 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_W);
395 } 379 }
396 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); 380 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
397 call(code, (uint8_t *)z80_write_word_highfirst); 381 call(code, opts->write_16_highfirst);
398 //no call to save_z80_reg needed since there's no chance we'll use the only 382 //no call to save_z80_reg needed since there's no chance we'll use the only
399 //the upper half of a register pair 383 //the upper half of a register pair
400 break; 384 break;
401 case Z80_POP: 385 case Z80_POP:
402 cycles(&opts->gen, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 8 : 4); 386 cycles(&opts->gen, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 8 : 4);
403 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); 387 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
404 call(code, (uint8_t *)z80_read_word); 388 call(code, opts->read_16);
405 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); 389 add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
406 if (inst->reg == Z80_AF) { 390 if (inst->reg == Z80_AF) {
407 391
408 bt_ir(code, 0, opts->gen.scratch1, SZ_W); 392 bt_ir(code, 0, opts->gen.scratch1, SZ_W);
409 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 393 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
450 } else { 434 } else {
451 xchg_rr(code, opts->regs[Z80_DE], opts->regs[Z80_HL], SZ_W); 435 xchg_rr(code, opts->regs[Z80_DE], opts->regs[Z80_HL], SZ_W);
452 } 436 }
453 } else { 437 } else {
454 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); 438 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
455 call(code, (uint8_t *)z80_read_byte); 439 call(code, opts->read_8);
456 xchg_rr(code, opts->regs[inst->reg], opts->gen.scratch1, SZ_B); 440 xchg_rr(code, opts->regs[inst->reg], opts->gen.scratch1, SZ_B);
457 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); 441 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
458 call(code, (uint8_t *)z80_write_byte); 442 call(code, opts->write_8);
459 cycles(&opts->gen, 1); 443 cycles(&opts->gen, 1);
460 uint8_t high_reg = z80_high_reg(inst->reg); 444 uint8_t high_reg = z80_high_reg(inst->reg);
461 uint8_t use_reg; 445 uint8_t use_reg;
462 //even though some of the upper halves can be used directly 446 //even though some of the upper halves can be used directly
463 //the limitations on mixing *H regs with the REX prefix 447 //the limitations on mixing *H regs with the REX prefix
464 //prevent us from taking advantage of it 448 //prevent us from taking advantage of it
465 use_reg = opts->regs[inst->reg]; 449 use_reg = opts->regs[inst->reg];
466 ror_ir(code, 8, use_reg, SZ_W); 450 ror_ir(code, 8, use_reg, SZ_W);
467 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); 451 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
468 add_ir(code, 1, opts->gen.scratch1, SZ_W); 452 add_ir(code, 1, opts->gen.scratch1, SZ_W);
469 call(code, (uint8_t *)z80_read_byte); 453 call(code, opts->read_8);
470 xchg_rr(code, use_reg, opts->gen.scratch1, SZ_B); 454 xchg_rr(code, use_reg, opts->gen.scratch1, SZ_B);
471 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); 455 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
472 add_ir(code, 1, opts->gen.scratch2, SZ_W); 456 add_ir(code, 1, opts->gen.scratch2, SZ_W);
473 call(code, (uint8_t *)z80_write_byte); 457 call(code, opts->write_8);
474 //restore reg to normal rotation 458 //restore reg to normal rotation
475 ror_ir(code, 8, use_reg, SZ_W); 459 ror_ir(code, 8, use_reg, SZ_W);
476 cycles(&opts->gen, 2); 460 cycles(&opts->gen, 2);
477 } 461 }
478 break; 462 break;
489 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_E), SZ_W); 473 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_E), SZ_W);
490 break; 474 break;
491 case Z80_LDI: { 475 case Z80_LDI: {
492 cycles(&opts->gen, 8); 476 cycles(&opts->gen, 8);
493 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); 477 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
494 call(code, (uint8_t *)z80_read_byte); 478 call(code, opts->read_8);
495 mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W); 479 mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W);
496 call(code, (uint8_t *)z80_write_byte); 480 call(code, opts->write_8);
497 cycles(&opts->gen, 2); 481 cycles(&opts->gen, 2);
498 add_ir(code, 1, opts->regs[Z80_DE], SZ_W); 482 add_ir(code, 1, opts->regs[Z80_DE], SZ_W);
499 add_ir(code, 1, opts->regs[Z80_HL], SZ_W); 483 add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
500 sub_ir(code, 1, opts->regs[Z80_BC], SZ_W); 484 sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
501 //TODO: Implement half-carry 485 //TODO: Implement half-carry
504 break; 488 break;
505 } 489 }
506 case Z80_LDIR: { 490 case Z80_LDIR: {
507 cycles(&opts->gen, 8); 491 cycles(&opts->gen, 8);
508 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); 492 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
509 call(code, (uint8_t *)z80_read_byte); 493 call(code, opts->read_8);
510 mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W); 494 mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W);
511 call(code, (uint8_t *)z80_write_byte); 495 call(code, opts->write_8);
512 add_ir(code, 1, opts->regs[Z80_DE], SZ_W); 496 add_ir(code, 1, opts->regs[Z80_DE], SZ_W);
513 add_ir(code, 1, opts->regs[Z80_HL], SZ_W); 497 add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
514 498
515 sub_ir(code, 1, opts->regs[Z80_BC], SZ_W); 499 sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
516 uint8_t * cont = code->cur+1; 500 uint8_t * cont = code->cur+1;
527 break; 511 break;
528 } 512 }
529 case Z80_LDD: { 513 case Z80_LDD: {
530 cycles(&opts->gen, 8); 514 cycles(&opts->gen, 8);
531 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); 515 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
532 call(code, (uint8_t *)z80_read_byte); 516 call(code, opts->read_8);
533 mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W); 517 mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W);
534 call(code, (uint8_t *)z80_write_byte); 518 call(code, opts->write_8);
535 cycles(&opts->gen, 2); 519 cycles(&opts->gen, 2);
536 sub_ir(code, 1, opts->regs[Z80_DE], SZ_W); 520 sub_ir(code, 1, opts->regs[Z80_DE], SZ_W);
537 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W); 521 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
538 sub_ir(code, 1, opts->regs[Z80_BC], SZ_W); 522 sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
539 //TODO: Implement half-carry 523 //TODO: Implement half-carry
542 break; 526 break;
543 } 527 }
544 case Z80_LDDR: { 528 case Z80_LDDR: {
545 cycles(&opts->gen, 8); 529 cycles(&opts->gen, 8);
546 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); 530 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
547 call(code, (uint8_t *)z80_read_byte); 531 call(code, opts->read_8);
548 mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W); 532 mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W);
549 call(code, (uint8_t *)z80_write_byte); 533 call(code, opts->write_8);
550 sub_ir(code, 1, opts->regs[Z80_DE], SZ_W); 534 sub_ir(code, 1, opts->regs[Z80_DE], SZ_W);
551 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W); 535 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
552 536
553 sub_ir(code, 1, opts->regs[Z80_BC], SZ_W); 537 sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
554 uint8_t * cont = code->cur+1; 538 uint8_t * cont = code->cur+1;
808 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 792 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
809 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 793 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
810 } 794 }
811 z80_save_reg(inst, opts); 795 z80_save_reg(inst, opts);
812 z80_save_ea(code, inst, opts); 796 z80_save_ea(code, inst, opts);
813 z80_save_result(code, inst); 797 z80_save_result(opts, inst);
814 break; 798 break;
815 case Z80_DEC: 799 case Z80_DEC:
816 num_cycles = 4; 800 num_cycles = 4;
817 if (inst->reg == Z80_IX || inst->reg == Z80_IY) { 801 if (inst->reg == Z80_IX || inst->reg == Z80_IY) {
818 num_cycles += 6; 802 num_cycles += 6;
834 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 818 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
835 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 819 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
836 } 820 }
837 z80_save_reg(inst, opts); 821 z80_save_reg(inst, opts);
838 z80_save_ea(code, inst, opts); 822 z80_save_ea(code, inst, opts);
839 z80_save_result(code, inst); 823 z80_save_result(opts, inst);
840 break; 824 break;
841 //case Z80_DAA: 825 //case Z80_DAA:
842 case Z80_CPL: 826 case Z80_CPL:
843 cycles(&opts->gen, 4); 827 cycles(&opts->gen, 4);
844 not_r(code, opts->regs[Z80_A], SZ_B); 828 not_r(code, opts->regs[Z80_A], SZ_B);
867 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 851 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
868 //TODO: Implement half-carry flag 852 //TODO: Implement half-carry flag
869 break; 853 break;
870 case Z80_NOP: 854 case Z80_NOP:
871 if (inst->immed == 42) { 855 if (inst->immed == 42) {
872 call(code, (uint8_t *)z80_save_context); 856 call(code, opts->gen.save_context);
873 mov_rr(code, opts->gen.context_reg, RDI, SZ_Q); 857 mov_rr(code, opts->gen.context_reg, RDI, SZ_Q);
874 jmp(code, (uint8_t *)z80_print_regs_exit); 858 jmp(code, (uint8_t *)z80_print_regs_exit);
875 } else { 859 } else {
876 cycles(&opts->gen, 4 * inst->immed); 860 cycles(&opts->gen, 4 * inst->immed);
877 } 861 }
878 break; 862 break;
879 case Z80_HALT: 863 case Z80_HALT: {
880 cycles(&opts->gen, 4); 864 cycles(&opts->gen, 4);
881 mov_ir(code, address, opts->gen.scratch1, SZ_W); 865 mov_ir(code, address, opts->gen.scratch1, SZ_W);
882 uint8_t * call_inst = code->cur; 866 uint8_t * call_inst = code->cur;
883 call(code, (uint8_t *)z80_halt); 867 mov_rr(code, opts->gen.limit, opts->gen.scratch2, SZ_D);
868 sub_rr(code, opts->gen.cycles, opts->gen.scratch2, SZ_D);
869 and_ir(code, 0xFFFFFFFC, opts->gen.scratch2, SZ_D);
870 add_rr(code, opts->gen.scratch2, opts->gen.cycles, SZ_D);
871 cmp_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D);
872 code_ptr skip_last = code->cur+1;
873 jcc(code, CC_B, opts->gen.handle_cycle_limit_int);
874 cycles(&opts->gen, 4);
875 *skip_last = code->cur - (skip_last+1);
876 call(code, opts->gen.handle_cycle_limit_int);
884 jmp(code, call_inst); 877 jmp(code, call_inst);
885 break; 878 break;
879 }
886 case Z80_DI: 880 case Z80_DI:
887 cycles(&opts->gen, 4); 881 cycles(&opts->gen, 4);
888 mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B); 882 mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
889 mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B); 883 mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
890 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, sync_cycle), opts->gen.limit, SZ_D); 884 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, sync_cycle), opts->gen.limit, SZ_D);
895 mov_rrdisp(code, opts->gen.cycles, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D); 889 mov_rrdisp(code, opts->gen.cycles, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D);
896 mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B); 890 mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
897 mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B); 891 mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
898 //interrupt enable has a one-instruction latency, minimum instruction duration is 4 cycles 892 //interrupt enable has a one-instruction latency, minimum instruction duration is 4 cycles
899 add_irdisp(code, 4, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D); 893 add_irdisp(code, 4, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D);
900 call(code, (uint8_t *)z80_do_sync); 894 call(code, opts->do_sync);
901 break; 895 break;
902 case Z80_IM: 896 case Z80_IM:
903 cycles(&opts->gen, 4); 897 cycles(&opts->gen, 4);
904 mov_irdisp(code, inst->immed, opts->gen.context_reg, offsetof(z80_context, im), SZ_B); 898 mov_irdisp(code, inst->immed, opts->gen.context_reg, offsetof(z80_context, im), SZ_B);
905 break; 899 break;
924 cmp_ir(code, 0, dst_op.base, SZ_B); 918 cmp_ir(code, 0, dst_op.base, SZ_B);
925 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 919 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
926 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 920 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
927 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 921 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
928 if (inst->addr_mode != Z80_UNUSED) { 922 if (inst->addr_mode != Z80_UNUSED) {
929 z80_save_result(code, inst); 923 z80_save_result(opts, inst);
930 if (src_op.mode != MODE_UNUSED) { 924 if (src_op.mode != MODE_UNUSED) {
931 z80_save_reg(inst, opts); 925 z80_save_reg(inst, opts);
932 } 926 }
933 } else { 927 } else {
934 z80_save_reg(inst, opts); 928 z80_save_reg(inst, opts);
956 cmp_ir(code, 0, dst_op.base, SZ_B); 950 cmp_ir(code, 0, dst_op.base, SZ_B);
957 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 951 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
958 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 952 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
959 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 953 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
960 if (inst->addr_mode != Z80_UNUSED) { 954 if (inst->addr_mode != Z80_UNUSED) {
961 z80_save_result(code, inst); 955 z80_save_result(opts, inst);
962 if (src_op.mode != MODE_UNUSED) { 956 if (src_op.mode != MODE_UNUSED) {
963 z80_save_reg(inst, opts); 957 z80_save_reg(inst, opts);
964 } 958 }
965 } else { 959 } else {
966 z80_save_reg(inst, opts); 960 z80_save_reg(inst, opts);
987 cmp_ir(code, 0, dst_op.base, SZ_B); 981 cmp_ir(code, 0, dst_op.base, SZ_B);
988 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 982 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
989 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 983 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
990 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 984 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
991 if (inst->addr_mode != Z80_UNUSED) { 985 if (inst->addr_mode != Z80_UNUSED) {
992 z80_save_result(code, inst); 986 z80_save_result(opts, inst);
993 if (src_op.mode != MODE_UNUSED) { 987 if (src_op.mode != MODE_UNUSED) {
994 z80_save_reg(inst, opts); 988 z80_save_reg(inst, opts);
995 } 989 }
996 } else { 990 } else {
997 z80_save_reg(inst, opts); 991 z80_save_reg(inst, opts);
1019 cmp_ir(code, 0, dst_op.base, SZ_B); 1013 cmp_ir(code, 0, dst_op.base, SZ_B);
1020 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 1014 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1021 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1015 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1022 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1016 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1023 if (inst->addr_mode != Z80_UNUSED) { 1017 if (inst->addr_mode != Z80_UNUSED) {
1024 z80_save_result(code, inst); 1018 z80_save_result(opts, inst);
1025 if (src_op.mode != MODE_UNUSED) { 1019 if (src_op.mode != MODE_UNUSED) {
1026 z80_save_reg(inst, opts); 1020 z80_save_reg(inst, opts);
1027 } 1021 }
1028 } else { 1022 } else {
1029 z80_save_reg(inst, opts); 1023 z80_save_reg(inst, opts);
1054 cmp_ir(code, 0, dst_op.base, SZ_B); 1048 cmp_ir(code, 0, dst_op.base, SZ_B);
1055 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 1049 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1056 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1050 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1057 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1051 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1058 if (inst->addr_mode != Z80_UNUSED) { 1052 if (inst->addr_mode != Z80_UNUSED) {
1059 z80_save_result(code, inst); 1053 z80_save_result(opts, inst);
1060 if (src_op.mode != MODE_UNUSED) { 1054 if (src_op.mode != MODE_UNUSED) {
1061 z80_save_reg(inst, opts); 1055 z80_save_reg(inst, opts);
1062 } 1056 }
1063 } else { 1057 } else {
1064 z80_save_reg(inst, opts); 1058 z80_save_reg(inst, opts);
1085 cmp_ir(code, 0, dst_op.base, SZ_B); 1079 cmp_ir(code, 0, dst_op.base, SZ_B);
1086 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 1080 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1087 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1081 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1088 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1082 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1089 if (inst->addr_mode != Z80_UNUSED) { 1083 if (inst->addr_mode != Z80_UNUSED) {
1090 z80_save_result(code, inst); 1084 z80_save_result(opts, inst);
1091 if (src_op.mode != MODE_UNUSED) { 1085 if (src_op.mode != MODE_UNUSED) {
1092 z80_save_reg(inst, opts); 1086 z80_save_reg(inst, opts);
1093 } 1087 }
1094 } else { 1088 } else {
1095 z80_save_reg(inst, opts); 1089 z80_save_reg(inst, opts);
1116 cmp_ir(code, 0, dst_op.base, SZ_B); 1110 cmp_ir(code, 0, dst_op.base, SZ_B);
1117 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 1111 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1118 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1112 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1119 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1113 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1120 if (inst->addr_mode != Z80_UNUSED) { 1114 if (inst->addr_mode != Z80_UNUSED) {
1121 z80_save_result(code, inst); 1115 z80_save_result(opts, inst);
1122 if (src_op.mode != MODE_UNUSED) { 1116 if (src_op.mode != MODE_UNUSED) {
1123 z80_save_reg(inst, opts); 1117 z80_save_reg(inst, opts);
1124 } 1118 }
1125 } else { 1119 } else {
1126 z80_save_reg(inst, opts); 1120 z80_save_reg(inst, opts);
1127 } 1121 }
1128 break; 1122 break;
1129 case Z80_RLD: 1123 case Z80_RLD:
1130 cycles(&opts->gen, 8); 1124 cycles(&opts->gen, 8);
1131 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); 1125 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
1132 call(code, (uint8_t *)z80_read_byte); 1126 call(code, opts->read_8);
1133 //Before: (HL) = 0x12, A = 0x34 1127 //Before: (HL) = 0x12, A = 0x34
1134 //After: (HL) = 0x24, A = 0x31 1128 //After: (HL) = 0x24, A = 0x31
1135 mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B); 1129 mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
1136 shl_ir(code, 4, opts->gen.scratch1, SZ_W); 1130 shl_ir(code, 4, opts->gen.scratch1, SZ_W);
1137 and_ir(code, 0xF, opts->gen.scratch2, SZ_W); 1131 and_ir(code, 0xF, opts->gen.scratch2, SZ_W);
1149 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1143 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1150 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1144 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1151 1145
1152 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W); 1146 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W);
1153 ror_ir(code, 8, opts->gen.scratch1, SZ_W); 1147 ror_ir(code, 8, opts->gen.scratch1, SZ_W);
1154 call(code, (uint8_t *)z80_write_byte); 1148 call(code, opts->write_8);
1155 break; 1149 break;
1156 case Z80_RRD: 1150 case Z80_RRD:
1157 cycles(&opts->gen, 8); 1151 cycles(&opts->gen, 8);
1158 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); 1152 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
1159 call(code, (uint8_t *)z80_read_byte); 1153 call(code, opts->read_8);
1160 //Before: (HL) = 0x12, A = 0x34 1154 //Before: (HL) = 0x12, A = 0x34
1161 //After: (HL) = 0x41, A = 0x32 1155 //After: (HL) = 0x41, A = 0x32
1162 movzx_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B, SZ_W); 1156 movzx_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B, SZ_W);
1163 ror_ir(code, 4, opts->gen.scratch1, SZ_W); 1157 ror_ir(code, 4, opts->gen.scratch1, SZ_W);
1164 shl_ir(code, 4, opts->gen.scratch2, SZ_W); 1158 shl_ir(code, 4, opts->gen.scratch2, SZ_W);
1179 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1173 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1180 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1174 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1181 1175
1182 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W); 1176 mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W);
1183 ror_ir(code, 8, opts->gen.scratch1, SZ_W); 1177 ror_ir(code, 8, opts->gen.scratch1, SZ_W);
1184 call(code, (uint8_t *)z80_write_byte); 1178 call(code, opts->write_8);
1185 break; 1179 break;
1186 case Z80_BIT: { 1180 case Z80_BIT: {
1187 num_cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16; 1181 num_cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16;
1188 cycles(&opts->gen, num_cycles); 1182 cycles(&opts->gen, num_cycles);
1189 uint8_t bit; 1183 uint8_t bit;
1245 } else { 1239 } else {
1246 mov_rr(code, src_op.base, dst_op.base, SZ_B); 1240 mov_rr(code, src_op.base, dst_op.base, SZ_B);
1247 } 1241 }
1248 } 1242 }
1249 if ((inst->addr_mode & 0x1F) != Z80_REG) { 1243 if ((inst->addr_mode & 0x1F) != Z80_REG) {
1250 z80_save_result(code, inst); 1244 z80_save_result(opts, inst);
1251 if (inst->reg != Z80_USE_IMMED) { 1245 if (inst->reg != Z80_USE_IMMED) {
1252 z80_save_reg(inst, opts); 1246 z80_save_reg(inst, opts);
1253 } 1247 }
1254 } 1248 }
1255 break; 1249 break;
1287 } else { 1281 } else {
1288 mov_rr(code, src_op.base, dst_op.base, SZ_B); 1282 mov_rr(code, src_op.base, dst_op.base, SZ_B);
1289 } 1283 }
1290 } 1284 }
1291 if (inst->addr_mode != Z80_REG) { 1285 if (inst->addr_mode != Z80_REG) {
1292 z80_save_result(code, inst); 1286 z80_save_result(opts, inst);
1293 if (inst->reg != Z80_USE_IMMED) { 1287 if (inst->reg != Z80_USE_IMMED) {
1294 z80_save_reg(inst, opts); 1288 z80_save_reg(inst, opts);
1295 } 1289 }
1296 } 1290 }
1297 break; 1291 break;
1316 if (inst->addr_mode == Z80_REG_INDIRECT) { 1310 if (inst->addr_mode == Z80_REG_INDIRECT) {
1317 mov_rr(code, opts->regs[inst->ea_reg], opts->gen.scratch1, SZ_W); 1311 mov_rr(code, opts->regs[inst->ea_reg], opts->gen.scratch1, SZ_W);
1318 } else { 1312 } else {
1319 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W); 1313 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
1320 } 1314 }
1321 call(code, (uint8_t *)z80_native_addr); 1315 call(code, opts->native_addr);
1322 jmp_r(code, opts->gen.scratch1); 1316 jmp_r(code, opts->gen.scratch1);
1323 } 1317 }
1324 break; 1318 break;
1325 } 1319 }
1326 case Z80_JPCC: { 1320 case Z80_JPCC: {
1361 call_dst + 256; 1355 call_dst + 256;
1362 } 1356 }
1363 jmp(code, call_dst); 1357 jmp(code, call_dst);
1364 } else { 1358 } else {
1365 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); 1359 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
1366 call(code, (uint8_t *)z80_native_addr); 1360 call(code, opts->native_addr);
1367 jmp_r(code, opts->gen.scratch1); 1361 jmp_r(code, opts->gen.scratch1);
1368 } 1362 }
1369 *no_jump_off = code->cur - (no_jump_off+1); 1363 *no_jump_off = code->cur - (no_jump_off+1);
1370 break; 1364 break;
1371 } 1365 }
1380 call_dst + 256; 1374 call_dst + 256;
1381 } 1375 }
1382 jmp(code, call_dst); 1376 jmp(code, call_dst);
1383 } else { 1377 } else {
1384 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); 1378 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
1385 call(code, (uint8_t *)z80_native_addr); 1379 call(code, opts->native_addr);
1386 jmp_r(code, opts->gen.scratch1); 1380 jmp_r(code, opts->gen.scratch1);
1387 } 1381 }
1388 break; 1382 break;
1389 } 1383 }
1390 case Z80_JRCC: { 1384 case Z80_JRCC: {
1415 call_dst + 256; 1409 call_dst + 256;
1416 } 1410 }
1417 jmp(code, call_dst); 1411 jmp(code, call_dst);
1418 } else { 1412 } else {
1419 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); 1413 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
1420 call(code, (uint8_t *)z80_native_addr); 1414 call(code, opts->native_addr);
1421 jmp_r(code, opts->gen.scratch1); 1415 jmp_r(code, opts->gen.scratch1);
1422 } 1416 }
1423 *no_jump_off = code->cur - (no_jump_off+1); 1417 *no_jump_off = code->cur - (no_jump_off+1);
1424 break; 1418 break;
1425 } 1419 }
1438 call_dst + 256; 1432 call_dst + 256;
1439 } 1433 }
1440 jmp(code, call_dst); 1434 jmp(code, call_dst);
1441 } else { 1435 } else {
1442 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); 1436 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
1443 call(code, (uint8_t *)z80_native_addr); 1437 call(code, opts->native_addr);
1444 jmp_r(code, opts->gen.scratch1); 1438 jmp_r(code, opts->gen.scratch1);
1445 } 1439 }
1446 *no_jump_off = code->cur - (no_jump_off+1); 1440 *no_jump_off = code->cur - (no_jump_off+1);
1447 break; 1441 break;
1448 case Z80_CALL: { 1442 case Z80_CALL: {
1449 cycles(&opts->gen, 11);//T States: 4,3,4 1443 cycles(&opts->gen, 11);//T States: 4,3,4
1450 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); 1444 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
1451 mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); 1445 mov_ir(code, address + 3, opts->gen.scratch1, SZ_W);
1452 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); 1446 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
1453 call(code, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3 1447 call(code, opts->write_16_highfirst);//T States: 3, 3
1454 if (inst->immed < 0x4000) { 1448 if (inst->immed < 0x4000) {
1455 code_ptr call_dst = z80_get_native_address(context, inst->immed); 1449 code_ptr call_dst = z80_get_native_address(context, inst->immed);
1456 if (!call_dst) { 1450 if (!call_dst) {
1457 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); 1451 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
1458 //fake address to force large displacement 1452 //fake address to force large displacement
1459 call_dst + 256; 1453 call_dst + 256;
1460 } 1454 }
1461 jmp(code, call_dst); 1455 jmp(code, call_dst);
1462 } else { 1456 } else {
1463 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W); 1457 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
1464 call(code, (uint8_t *)z80_native_addr); 1458 call(code, opts->native_addr);
1465 jmp_r(code, opts->gen.scratch1); 1459 jmp_r(code, opts->gen.scratch1);
1466 } 1460 }
1467 break; 1461 break;
1468 } 1462 }
1469 case Z80_CALLCC: 1463 case Z80_CALLCC:
1496 jcc(code, cond, code->cur+2); 1490 jcc(code, cond, code->cur+2);
1497 cycles(&opts->gen, 1);//Last of the above T states takes an extra cycle in the true case 1491 cycles(&opts->gen, 1);//Last of the above T states takes an extra cycle in the true case
1498 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); 1492 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
1499 mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); 1493 mov_ir(code, address + 3, opts->gen.scratch1, SZ_W);
1500 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); 1494 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
1501 call(code, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3 1495 call(code, opts->write_16_highfirst);//T States: 3, 3
1502 if (inst->immed < 0x4000) { 1496 if (inst->immed < 0x4000) {
1503 code_ptr call_dst = z80_get_native_address(context, inst->immed); 1497 code_ptr call_dst = z80_get_native_address(context, inst->immed);
1504 if (!call_dst) { 1498 if (!call_dst) {
1505 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); 1499 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
1506 //fake address to force large displacement 1500 //fake address to force large displacement
1507 call_dst + 256; 1501 call_dst + 256;
1508 } 1502 }
1509 jmp(code, call_dst); 1503 jmp(code, call_dst);
1510 } else { 1504 } else {
1511 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W); 1505 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
1512 call(code, (uint8_t *)z80_native_addr); 1506 call(code, opts->native_addr);
1513 jmp_r(code, opts->gen.scratch1); 1507 jmp_r(code, opts->gen.scratch1);
1514 } 1508 }
1515 *no_call_off = code->cur - (no_call_off+1); 1509 *no_call_off = code->cur - (no_call_off+1);
1516 break; 1510 break;
1517 case Z80_RET: 1511 case Z80_RET:
1518 cycles(&opts->gen, 4);//T States: 4 1512 cycles(&opts->gen, 4);//T States: 4
1519 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); 1513 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
1520 call(code, (uint8_t *)z80_read_word);//T STates: 3, 3 1514 call(code, opts->read_16);//T STates: 3, 3
1521 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); 1515 add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
1522 call(code, (uint8_t *)z80_native_addr); 1516 call(code, opts->native_addr);
1523 jmp_r(code, opts->gen.scratch1); 1517 jmp_r(code, opts->gen.scratch1);
1524 break; 1518 break;
1525 case Z80_RETCC: { 1519 case Z80_RETCC: {
1526 cycles(&opts->gen, 5);//T States: 5 1520 cycles(&opts->gen, 5);//T States: 5
1527 uint8_t cond = CC_Z; 1521 uint8_t cond = CC_Z;
1549 break; 1543 break;
1550 } 1544 }
1551 uint8_t *no_call_off = code->cur+1; 1545 uint8_t *no_call_off = code->cur+1;
1552 jcc(code, cond, code->cur+2); 1546 jcc(code, cond, code->cur+2);
1553 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); 1547 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
1554 call(code, (uint8_t *)z80_read_word);//T STates: 3, 3 1548 call(code, opts->read_16);//T STates: 3, 3
1555 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); 1549 add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
1556 call(code, (uint8_t *)z80_native_addr); 1550 call(code, opts->native_addr);
1557 jmp_r(code, opts->gen.scratch1); 1551 jmp_r(code, opts->gen.scratch1);
1558 *no_call_off = code->cur - (no_call_off+1); 1552 *no_call_off = code->cur - (no_call_off+1);
1559 break; 1553 break;
1560 } 1554 }
1561 case Z80_RETI: 1555 case Z80_RETI:
1562 //For some systems, this may need a callback for signalling interrupt routine completion 1556 //For some systems, this may need a callback for signalling interrupt routine completion
1563 cycles(&opts->gen, 8);//T States: 4, 4 1557 cycles(&opts->gen, 8);//T States: 4, 4
1564 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); 1558 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
1565 call(code, (uint8_t *)z80_read_word);//T STates: 3, 3 1559 call(code, opts->read_16);//T STates: 3, 3
1566 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); 1560 add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
1567 call(code, (uint8_t *)z80_native_addr); 1561 call(code, opts->native_addr);
1568 jmp_r(code, opts->gen.scratch1); 1562 jmp_r(code, opts->gen.scratch1);
1569 break; 1563 break;
1570 case Z80_RETN: 1564 case Z80_RETN:
1571 cycles(&opts->gen, 8);//T States: 4, 4 1565 cycles(&opts->gen, 8);//T States: 4, 4
1572 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, iff2), opts->gen.scratch2, SZ_B); 1566 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, iff2), opts->gen.scratch2, SZ_B);
1573 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); 1567 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
1574 mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B); 1568 mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
1575 call(code, (uint8_t *)z80_read_word);//T STates: 3, 3 1569 call(code, opts->read_16);//T STates: 3, 3
1576 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); 1570 add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
1577 call(code, (uint8_t *)z80_native_addr); 1571 call(code, opts->native_addr);
1578 jmp_r(code, opts->gen.scratch1); 1572 jmp_r(code, opts->gen.scratch1);
1579 break; 1573 break;
1580 case Z80_RST: { 1574 case Z80_RST: {
1581 //RST is basically CALL to an address in page 0 1575 //RST is basically CALL to an address in page 0
1582 cycles(&opts->gen, 5);//T States: 5 1576 cycles(&opts->gen, 5);//T States: 5
1583 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); 1577 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
1584 mov_ir(code, address + 1, opts->gen.scratch1, SZ_W); 1578 mov_ir(code, address + 1, opts->gen.scratch1, SZ_W);
1585 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); 1579 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
1586 call(code, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3 1580 call(code, opts->write_16_highfirst);//T States: 3, 3
1587 code_ptr call_dst = z80_get_native_address(context, inst->immed); 1581 code_ptr call_dst = z80_get_native_address(context, inst->immed);
1588 if (!call_dst) { 1582 if (!call_dst) {
1589 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); 1583 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
1590 //fake address to force large displacement 1584 //fake address to force large displacement
1591 call_dst + 256; 1585 call_dst + 256;
1598 if (inst->addr_mode == Z80_IMMED_INDIRECT) { 1592 if (inst->addr_mode == Z80_IMMED_INDIRECT) {
1599 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_B); 1593 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_B);
1600 } else { 1594 } else {
1601 mov_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); 1595 mov_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
1602 } 1596 }
1603 call(code, (uint8_t *)z80_io_read); 1597 call(code, opts->read_io);
1604 translate_z80_reg(inst, &dst_op, opts); 1598 translate_z80_reg(inst, &dst_op, opts);
1605 mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_B); 1599 mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_B);
1606 z80_save_reg(inst, opts); 1600 z80_save_reg(inst, opts);
1607 break; 1601 break;
1608 /*case Z80_INI: 1602 /*case Z80_INI:
1616 } else { 1610 } else {
1617 mov_rr(code, opts->regs[Z80_C], opts->gen.scratch2, SZ_B); 1611 mov_rr(code, opts->regs[Z80_C], opts->gen.scratch2, SZ_B);
1618 } 1612 }
1619 translate_z80_reg(inst, &src_op, opts); 1613 translate_z80_reg(inst, &src_op, opts);
1620 mov_rr(code, dst_op.base, opts->gen.scratch1, SZ_B); 1614 mov_rr(code, dst_op.base, opts->gen.scratch1, SZ_B);
1621 call(code, (uint8_t *)z80_io_write); 1615 call(code, opts->write_io);
1622 z80_save_reg(inst, opts); 1616 z80_save_reg(inst, opts);
1623 break; 1617 break;
1624 /*case Z80_OUTI: 1618 /*case Z80_OUTI:
1625 case Z80_OTIR: 1619 case Z80_OTIR:
1626 case Z80_OUTD: 1620 case Z80_OUTD:
1735 code_ptr dst = z80_get_native_address(context, inst_start); 1729 code_ptr dst = z80_get_native_address(context, inst_start);
1736 code_info code = {dst, dst+16}; 1730 code_info code = {dst, dst+16};
1737 z80_options * opts = context->options; 1731 z80_options * opts = context->options;
1738 dprintf("patching code at %p for Z80 instruction at %X due to write to %X\n", code, inst_start, address); 1732 dprintf("patching code at %p for Z80 instruction at %X due to write to %X\n", code, inst_start, address);
1739 mov_ir(&code, inst_start, opts->gen.scratch1, SZ_D); 1733 mov_ir(&code, inst_start, opts->gen.scratch1, SZ_D);
1740 call(&code, (uint8_t *)z80_retrans_stub); 1734 call(&code, opts->retrans_stub);
1741 } 1735 }
1742 return context; 1736 return context;
1743 } 1737 }
1744 1738
1745 uint8_t * z80_get_native_address_trans(z80_context * context, uint32_t address) 1739 uint8_t * z80_get_native_address_trans(z80_context * context, uint32_t address)
1957 for (int i = 0; i <= Z80_A; i++) 1951 for (int i = 0; i <= Z80_A; i++)
1958 { 1952 {
1959 int reg; 1953 int reg;
1960 uint8_t size; 1954 uint8_t size;
1961 if (i < Z80_I) { 1955 if (i < Z80_I) {
1962 int reg = i /2 + Z80_BC; 1956 reg = i /2 + Z80_BC;
1963 size = SZ_W; 1957 size = SZ_W;
1958 i++;
1964 1959
1965 } else { 1960 } else {
1966 reg = i; 1961 reg = i;
1967 size = SZ_B; 1962 size = SZ_B;
1968 } 1963 }
1975 } 1970 }
1976 mov_rrdisp(code, options->gen.limit, options->gen.context_reg, offsetof(z80_context, target_cycle), SZ_D); 1971 mov_rrdisp(code, options->gen.limit, options->gen.context_reg, offsetof(z80_context, target_cycle), SZ_D);
1977 mov_rrdisp(code, options->gen.cycles, options->gen.context_reg, offsetof(z80_context, current_cycle), SZ_D); 1972 mov_rrdisp(code, options->gen.cycles, options->gen.context_reg, offsetof(z80_context, current_cycle), SZ_D);
1978 mov_rrdisp(code, options->bank_reg, options->gen.context_reg, offsetof(z80_context, bank_reg), SZ_W); 1973 mov_rrdisp(code, options->bank_reg, options->gen.context_reg, offsetof(z80_context, bank_reg), SZ_W);
1979 mov_rrdisp(code, options->bank_pointer, options->gen.context_reg, offsetof(z80_context, mem_pointers) + sizeof(uint8_t *) * 1, SZ_PTR); 1974 mov_rrdisp(code, options->bank_pointer, options->gen.context_reg, offsetof(z80_context, mem_pointers) + sizeof(uint8_t *) * 1, SZ_PTR);
1975 retn(code);
1980 1976
1981 options->load_context_scratch = code->cur; 1977 options->load_context_scratch = code->cur;
1982 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, scratch1), options->gen.scratch1, SZ_W); 1978 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, scratch1), options->gen.scratch1, SZ_W);
1983 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, scratch2), options->gen.scratch2, SZ_W); 1979 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, scratch2), options->gen.scratch2, SZ_W);
1984 options->gen.load_context = code->cur; 1980 options->gen.load_context = code->cur;
2003 } 1999 }
2004 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.limit, SZ_D); 2000 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.limit, SZ_D);
2005 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, current_cycle), options->gen.cycles, SZ_D); 2001 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, current_cycle), options->gen.cycles, SZ_D);
2006 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, bank_reg), options->bank_reg, SZ_W); 2002 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, bank_reg), options->bank_reg, SZ_W);
2007 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, mem_pointers) + sizeof(uint8_t *) * 1, options->bank_pointer, SZ_PTR); 2003 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, mem_pointers) + sizeof(uint8_t *) * 1, options->bank_pointer, SZ_PTR);
2004 retn(code);
2005
2006 options->native_addr = code->cur;
2007 call(code, options->gen.save_context);
2008 push_r(code, options->gen.context_reg);
2009 mov_rr(code, options->gen.context_reg, RDI, SZ_PTR);
2010 movzx_rr(code, options->gen.scratch1, RSI, SZ_W, SZ_D);
2011 call(code, (code_ptr)z80_get_native_address_trans);
2012 mov_rr(code, RAX, options->gen.scratch1, SZ_PTR);
2013 pop_r(code, options->gen.context_reg);
2014 call(code, options->gen.load_context);
2015 retn(code);
2008 2016
2009 options->gen.handle_cycle_limit = code->cur; 2017 options->gen.handle_cycle_limit = code->cur;
2010 cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.cycles, SZ_D); 2018 cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.cycles, SZ_D);
2011 code_ptr no_sync = code->cur+1; 2019 code_ptr no_sync = code->cur+1;
2012 jcc(code, CC_B, no_sync); 2020 jcc(code, CC_B, no_sync);
2063 call(code, options->write_8_noinc); 2071 call(code, options->write_8_noinc);
2064 //dispose of return address as we'll be jumping somewhere else 2072 //dispose of return address as we'll be jumping somewhere else
2065 pop_r(code, options->gen.scratch2); 2073 pop_r(code, options->gen.scratch2);
2066 //TODO: Support interrupt mode 0 and 2 2074 //TODO: Support interrupt mode 0 and 2
2067 mov_ir(code, 0x38, options->gen.scratch1, SZ_W); 2075 mov_ir(code, 0x38, options->gen.scratch1, SZ_W);
2068 call(code, (code_ptr)z80_native_addr); 2076 call(code, options->native_addr);
2069 jmp_r(code, options->gen.scratch1); 2077 jmp_r(code, options->gen.scratch1);
2078 *skip_int = code->cur - (skip_int+1);
2079 cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.cycles, SZ_D);
2080 code_ptr skip_sync = code->cur + 1;
2081 jcc(code, CC_B, skip_sync);
2082 options->do_sync = code->cur;
2083 call(code, options->gen.save_context);
2084 pop_rind(code, options->gen.context_reg);
2085 //restore callee saved registers
2086 pop_r(code, R15);
2087 pop_r(code, R14);
2088 pop_r(code, R13);
2089 pop_r(code, R12);
2090 pop_r(code, RBP);
2091 pop_r(code, RBX);
2092 //return to caller of z80_run
2093 *skip_sync = code->cur - (skip_sync+1);
2094 retn(code);
2095
2096 options->read_io = code->cur;
2097 check_cycles(&options->gen);
2098 cycles(&options->gen, 4);
2099 //Genesis has no IO hardware and always returns FF
2100 //eventually this should use a second memory map array
2101 mov_ir(code, 0xFF, options->gen.scratch1, SZ_B);
2102 retn(code);
2103
2104 options->write_io = code->cur;
2105 check_cycles(&options->gen);
2106 cycles(&options->gen, 4);
2107 retn(code);
2108
2109 options->retrans_stub = code->cur;
2110 //pop return address
2111 pop_r(code, options->gen.scratch2);
2112 call(code, options->gen.save_context);
2113 //adjust pointer before move and call instructions that got us here
2114 sub_ir(code, 11, options->gen.scratch2, SZ_PTR);
2115 mov_rr(code, options->gen.scratch1, RDI, SZ_D);
2116 mov_rr(code, options->gen.scratch2, RDX, SZ_PTR);
2117 push_r(code, options->gen.context_reg);
2118 call(code, (code_ptr)z80_retranslate_inst);
2119 pop_r(code, options->gen.context_reg);
2120 mov_rr(code, RAX, options->gen.scratch1, SZ_PTR);
2121 call(code, options->gen.load_context);
2122 jmp_r(code, options->gen.scratch1);
2123
2124 options->run = (z80_run_fun)code->cur;
2125 //save callee save registers
2126 push_r(code, RBX);
2127 push_r(code, RBP);
2128 push_r(code, R12);
2129 push_r(code, R13);
2130 push_r(code, R14);
2131 push_r(code, R15);
2132 mov_rr(code, RDI, options->gen.context_reg, SZ_PTR);
2133 cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR);
2134 code_ptr no_extra = code->cur+1;
2135 jcc(code, CC_Z, no_extra);
2136 push_rdisp(code, options->gen.context_reg, offsetof(z80_context, extra_pc));
2137 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR);
2138 *no_extra = code->cur - (no_extra + 1);
2139 jmp_rind(code, options->gen.context_reg);
2070 } 2140 }
2071 2141
2072 void * z80_gen_bank_write(uint32_t start_address, void * voptions) 2142 void * z80_gen_bank_write(uint32_t start_address, void * voptions)
2073 { 2143 {
2074 z80_options * options = voptions; 2144 z80_options * options = voptions;
2084 context->static_code_map->offsets = malloc(sizeof(int32_t) * 0x2000); 2154 context->static_code_map->offsets = malloc(sizeof(int32_t) * 0x2000);
2085 memset(context->static_code_map->offsets, 0xFF, sizeof(int32_t) * 0x2000); 2155 memset(context->static_code_map->offsets, 0xFF, sizeof(int32_t) * 0x2000);
2086 context->banked_code_map = malloc(sizeof(native_map_slot) * (1 << 9)); 2156 context->banked_code_map = malloc(sizeof(native_map_slot) * (1 << 9));
2087 memset(context->banked_code_map, 0, sizeof(native_map_slot) * (1 << 9)); 2157 memset(context->banked_code_map, 0, sizeof(native_map_slot) * (1 << 9));
2088 context->options = options; 2158 context->options = options;
2159 context->run = options->run;
2089 } 2160 }
2090 2161
2091 void z80_reset(z80_context * context) 2162 void z80_reset(z80_context * context)
2092 { 2163 {
2093 context->im = 0; 2164 context->im = 0;
2113 check_cycles_int(&opts->gen, address); 2184 check_cycles_int(&opts->gen, address);
2114 int check_int_size = code->cur-bp_stub; 2185 int check_int_size = code->cur-bp_stub;
2115 code->cur = bp_stub; 2186 code->cur = bp_stub;
2116 2187
2117 //Save context and call breakpoint handler 2188 //Save context and call breakpoint handler
2118 call(code, (uint8_t *)z80_save_context); 2189 call(code, opts->gen.save_context);
2119 push_r(code, opts->gen.scratch1); 2190 push_r(code, opts->gen.scratch1);
2120 mov_rr(code, opts->gen.context_reg, RDI, SZ_Q); 2191 mov_rr(code, opts->gen.context_reg, RDI, SZ_Q);
2121 mov_rr(code, opts->gen.scratch1, RSI, SZ_W); 2192 mov_rr(code, opts->gen.scratch1, RSI, SZ_W);
2122 call(code, bp_handler); 2193 call(code, bp_handler);
2123 mov_rr(code, RAX, opts->gen.context_reg, SZ_Q); 2194 mov_rr(code, RAX, opts->gen.context_reg, SZ_Q);
2124 //Restore context 2195 //Restore context
2125 call(code, (uint8_t *)z80_load_context); 2196 call(code, opts->gen.load_context);
2126 pop_r(code, opts->gen.scratch1); 2197 pop_r(code, opts->gen.scratch1);
2127 //do prologue stuff 2198 //do prologue stuff
2128 cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D); 2199 cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D);
2129 uint8_t * jmp_off = code->cur+1; 2200 uint8_t * jmp_off = code->cur+1;
2130 jcc(code, CC_NC, code->cur + 7); 2201 jcc(code, CC_NC, code->cur + 7);
2131 pop_r(code, opts->gen.scratch1); 2202 pop_r(code, opts->gen.scratch1);
2132 add_ir(code, check_int_size - (code->cur-native), opts->gen.scratch1, SZ_Q); 2203 add_ir(code, check_int_size - (code->cur-native), opts->gen.scratch1, SZ_Q);
2133 push_r(code, opts->gen.scratch1); 2204 push_r(code, opts->gen.scratch1);
2134 jmp(code, (uint8_t *)z80_handle_cycle_limit_int); 2205 jmp(code, opts->gen.handle_cycle_limit_int);
2135 *jmp_off = code->cur - (jmp_off+1); 2206 *jmp_off = code->cur - (jmp_off+1);
2136 //jump back to body of translated instruction 2207 //jump back to body of translated instruction
2137 pop_r(code, opts->gen.scratch1); 2208 pop_r(code, opts->gen.scratch1);
2138 add_ir(code, check_int_size - (code->cur-native), opts->gen.scratch1, SZ_Q); 2209 add_ir(code, check_int_size - (code->cur-native), opts->gen.scratch1, SZ_Q);
2139 jmp_r(code, opts->gen.scratch1); 2210 jmp_r(code, opts->gen.scratch1);