Mercurial > repos > blastem
comparison z80_to_x86.c @ 236:19fb3523a9e5
Implement more Z80 instructions (untested)
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 25 Apr 2013 22:49:36 -0700 |
parents | d9bf8e61c33c |
children | 827ebce557bf |
comparison
equal
deleted
inserted
replaced
235:d9bf8e61c33c | 236:19fb3523a9e5 |
---|---|
364 dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z)); | 364 dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z)); |
365 dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S)); | 365 dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S)); |
366 dst = z80_save_reg(dst, inst, opts); | 366 dst = z80_save_reg(dst, inst, opts); |
367 dst = z80_save_ea(dst, inst, opts); | 367 dst = z80_save_ea(dst, inst, opts); |
368 break; | 368 break; |
369 /*case Z80_SBC: | 369 //case Z80_SBC: |
370 case Z80_AND: | 370 case Z80_AND: |
371 cycles = 4; | |
372 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { | |
373 cycles += 12; | |
374 } else if(inst->addr_mode == Z80_IMMED) { | |
375 cycles += 3; | |
376 } else if(z80_size(inst) == SZ_W) { | |
377 cycles += 4; | |
378 } | |
379 dst = zcycles(dst, cycles); | |
380 dst = translate_z80_reg(inst, &dst_op, dst, opts); | |
381 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); | |
382 if (src_op.mode == MODE_REG_DIRECT) { | |
383 dst = and_rr(dst, src_op.base, dst_op.base, z80_size(inst)); | |
384 } else { | |
385 dst = and_ir(dst, src_op.disp, dst_op.base, z80_size(inst)); | |
386 } | |
387 //TODO: Cleanup flags | |
388 dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C)); | |
389 dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B); | |
390 //TODO: Implement half-carry flag | |
391 if (z80_size(inst) == SZ_B) { | |
392 dst = setcc_rdisp8(dst, CC_O, CONTEXT, zf_off(ZF_PV)); | |
393 dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z)); | |
394 dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S)); | |
395 } | |
396 dst = z80_save_reg(dst, inst, opts); | |
397 dst = z80_save_ea(dst, inst, opts); | |
398 break; | |
371 case Z80_OR: | 399 case Z80_OR: |
400 cycles = 4; | |
401 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { | |
402 cycles += 12; | |
403 } else if(inst->addr_mode == Z80_IMMED) { | |
404 cycles += 3; | |
405 } else if(z80_size(inst) == SZ_W) { | |
406 cycles += 4; | |
407 } | |
408 dst = zcycles(dst, cycles); | |
409 dst = translate_z80_reg(inst, &dst_op, dst, opts); | |
410 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); | |
411 if (src_op.mode == MODE_REG_DIRECT) { | |
412 dst = or_rr(dst, src_op.base, dst_op.base, z80_size(inst)); | |
413 } else { | |
414 dst = or_ir(dst, src_op.disp, dst_op.base, z80_size(inst)); | |
415 } | |
416 //TODO: Cleanup flags | |
417 dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C)); | |
418 dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B); | |
419 //TODO: Implement half-carry flag | |
420 if (z80_size(inst) == SZ_B) { | |
421 dst = setcc_rdisp8(dst, CC_O, CONTEXT, zf_off(ZF_PV)); | |
422 dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z)); | |
423 dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S)); | |
424 } | |
425 dst = z80_save_reg(dst, inst, opts); | |
426 dst = z80_save_ea(dst, inst, opts); | |
427 break; | |
372 case Z80_XOR: | 428 case Z80_XOR: |
373 case Z80_CP:*/ | 429 cycles = 4; |
430 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { | |
431 cycles += 12; | |
432 } else if(inst->addr_mode == Z80_IMMED) { | |
433 cycles += 3; | |
434 } else if(z80_size(inst) == SZ_W) { | |
435 cycles += 4; | |
436 } | |
437 dst = zcycles(dst, cycles); | |
438 dst = translate_z80_reg(inst, &dst_op, dst, opts); | |
439 dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); | |
440 if (src_op.mode == MODE_REG_DIRECT) { | |
441 dst = add_rr(dst, src_op.base, dst_op.base, z80_size(inst)); | |
442 } else { | |
443 dst = add_ir(dst, src_op.disp, dst_op.base, z80_size(inst)); | |
444 } | |
445 //TODO: Cleanup flags | |
446 dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C)); | |
447 dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B); | |
448 //TODO: Implement half-carry flag | |
449 if (z80_size(inst) == SZ_B) { | |
450 dst = setcc_rdisp8(dst, CC_O, CONTEXT, zf_off(ZF_PV)); | |
451 dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z)); | |
452 dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S)); | |
453 } | |
454 dst = z80_save_reg(dst, inst, opts); | |
455 dst = z80_save_ea(dst, inst, opts); | |
456 break; | |
457 //case Z80_CP:*/ | |
374 case Z80_INC: | 458 case Z80_INC: |
375 cycles = 4; | 459 cycles = 4; |
376 if (inst->reg == Z80_IX || inst->reg == Z80_IY) { | 460 if (inst->reg == Z80_IX || inst->reg == Z80_IY) { |
377 cycles += 6; | 461 cycles += 6; |
378 } else if(z80_size(inst) == SZ_W) { | 462 } else if(z80_size(inst) == SZ_W) { |
393 dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S)); | 477 dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S)); |
394 } | 478 } |
395 dst = z80_save_reg(dst, inst, opts); | 479 dst = z80_save_reg(dst, inst, opts); |
396 dst = z80_save_ea(dst, inst, opts); | 480 dst = z80_save_ea(dst, inst, opts); |
397 break; | 481 break; |
398 /*case Z80_DEC: | 482 case Z80_DEC: |
399 break; | 483 cycles = 4; |
400 case Z80_DAA: | 484 if (inst->reg == Z80_IX || inst->reg == Z80_IY) { |
485 cycles += 6; | |
486 } else if(z80_size(inst) == SZ_W) { | |
487 cycles += 2; | |
488 } else if(inst->reg == Z80_IXH || inst->reg == Z80_IXL || inst->reg == Z80_IYH || inst->reg == Z80_IYL || inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { | |
489 cycles += 4; | |
490 } | |
491 dst = translate_z80_reg(inst, &dst_op, dst, opts); | |
492 if (dst_op.mode == MODE_UNUSED) { | |
493 dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY); | |
494 } | |
495 dst = sub_ir(dst, 1, dst_op.base, z80_size(inst)); | |
496 if (z80_size(inst) == SZ_B) { | |
497 dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B); | |
498 //TODO: Implement half-carry flag | |
499 dst = setcc_rdisp8(dst, CC_O, CONTEXT, zf_off(ZF_PV)); | |
500 dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z)); | |
501 dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S)); | |
502 } | |
503 dst = z80_save_reg(dst, inst, opts); | |
504 dst = z80_save_ea(dst, inst, opts); | |
505 break; | |
506 /*case Z80_DAA: | |
401 case Z80_CPL: | 507 case Z80_CPL: |
402 case Z80_NEG: | 508 case Z80_NEG: |
403 case Z80_CCF: | 509 case Z80_CCF: |
404 case Z80_SCF:*/ | 510 case Z80_SCF:*/ |
405 case Z80_NOP: | 511 case Z80_NOP: |
425 case Z80_SRL: | 531 case Z80_SRL: |
426 case Z80_RLD: | 532 case Z80_RLD: |
427 case Z80_RRD: | 533 case Z80_RRD: |
428 case Z80_BIT: | 534 case Z80_BIT: |
429 case Z80_SET: | 535 case Z80_SET: |
430 case Z80_RES: | 536 case Z80_RES:*/ |
431 case Z80_JP: | 537 case Z80_JP: { |
432 case Z80_JPCC: | 538 cycles = 4; |
433 case Z80_JR:*/ | 539 if (inst->addr_mode != MODE_REG_INDIRECT) { |
540 cycles += 6; | |
541 } else if(inst->ea_reg == Z80_IX || inst->ea_reg == Z80_IY) { | |
542 cycles += 4; | |
543 } | |
544 dst = zcycles(dst, cycles); | |
545 if (inst->addr_mode != MODE_REG_INDIRECT && inst->immed < 0x4000) { | |
546 uint8_t * call_dst = z80_get_native_address(context, inst->immed); | |
547 if (!call_dst) { | |
548 opts->deferred = defer_address(opts->deferred, inst->immed, dst + 1); | |
549 //fake address to force large displacement | |
550 call_dst = dst + 256; | |
551 } | |
552 dst = jmp(dst, call_dst); | |
553 } else { | |
554 if (inst->addr_mode == MODE_REG_INDIRECT) { | |
555 dst = mov_rr(dst, opts->regs[inst->ea_reg], SCRATCH1, SZ_W); | |
556 } else { | |
557 dst = mov_ir(dst, inst->immed, SCRATCH1, SZ_W); | |
558 } | |
559 dst = call(dst, (uint8_t *)z80_native_addr); | |
560 dst = jmp_r(dst, SCRATCH1); | |
561 } | |
562 break; | |
563 } | |
564 case Z80_JPCC: { | |
565 dst = zcycles(dst, 7);//T States: 4,3 | |
566 uint8_t cond = CC_Z; | |
567 switch (inst->reg) | |
568 { | |
569 case Z80_CC_NZ: | |
570 cond = CC_NZ; | |
571 case Z80_CC_Z: | |
572 dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_Z), SZ_B); | |
573 break; | |
574 case Z80_CC_NC: | |
575 cond = CC_NZ; | |
576 case Z80_CC_C: | |
577 dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_C), SZ_B); | |
578 break; | |
579 } | |
580 uint8_t *no_jump_off = dst+1; | |
581 dst = jcc(dst, cond, dst+2); | |
582 dst = zcycles(dst, 5);//T States: 5 | |
583 uint16_t dest_addr = inst->immed; | |
584 if (dest_addr < 0x4000) { | |
585 uint8_t * call_dst = z80_get_native_address(context, dest_addr); | |
586 if (!call_dst) { | |
587 opts->deferred = defer_address(opts->deferred, dest_addr, dst + 1); | |
588 //fake address to force large displacement | |
589 call_dst = dst + 256; | |
590 } | |
591 dst = jmp(dst, call_dst); | |
592 } else { | |
593 dst = mov_ir(dst, dest_addr, SCRATCH1, SZ_W); | |
594 dst = call(dst, (uint8_t *)z80_native_addr); | |
595 dst = jmp_r(dst, SCRATCH1); | |
596 } | |
597 *no_jump_off = dst - (no_jump_off+1); | |
598 break; | |
599 } | |
600 case Z80_JR: { | |
601 dst = zcycles(dst, 12);//T States: 4,3,5 | |
602 uint16_t dest_addr = address + inst->immed + 2; | |
603 if (dest_addr < 0x4000) { | |
604 uint8_t * call_dst = z80_get_native_address(context, dest_addr); | |
605 if (!call_dst) { | |
606 opts->deferred = defer_address(opts->deferred, dest_addr, dst + 1); | |
607 //fake address to force large displacement | |
608 call_dst = dst + 256; | |
609 } | |
610 dst = jmp(dst, call_dst); | |
611 } else { | |
612 dst = mov_ir(dst, dest_addr, SCRATCH1, SZ_W); | |
613 dst = call(dst, (uint8_t *)z80_native_addr); | |
614 dst = jmp_r(dst, SCRATCH1); | |
615 } | |
616 break; | |
617 } | |
434 case Z80_JRCC: { | 618 case Z80_JRCC: { |
435 dst = zcycles(dst, 7);//T States: 4,3 | 619 dst = zcycles(dst, 7);//T States: 4,3 |
436 uint8_t cond = CC_Z; | 620 uint8_t cond = CC_Z; |
437 switch (inst->reg) | 621 switch (inst->reg) |
438 { | 622 { |