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 {