Mercurial > repos > blastem
comparison m68k_to_x86.c @ 46:f2aaaf36c875
Add support for dbcc instruction
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 12 Dec 2012 20:18:06 -0800 |
parents | 4717146a7606 |
children | d2e43d64e999 |
comparison
equal
deleted
inserted
replaced
45:3adbd97f71f2 | 46:f2aaaf36c875 |
---|---|
344 dst = mov_rdisp8r(dst, src.base, src.disp, reg, inst->extra.size); | 344 dst = mov_rdisp8r(dst, src.base, src.disp, reg, inst->extra.size); |
345 } else { | 345 } else { |
346 dst = mov_ir(dst, src.disp, reg, inst->extra.size); | 346 dst = mov_ir(dst, src.disp, reg, inst->extra.size); |
347 } | 347 } |
348 } else if(src.mode == MODE_REG_DIRECT) { | 348 } else if(src.mode == MODE_REG_DIRECT) { |
349 printf("mov_rrdisp8 from reg %d to offset %d from reg %d (%d)\n", src.base, (inst->dst.addr_mode == MODE_REG ? offsetof(m68k_context, dregs) : offsetof(m68k_context, aregs)) + 4 * inst->dst.params.regs.pri, CONTEXT, inst->dst.params.regs.pri); | 349 printf("mov_rrdisp8 from reg %d to offset %d from reg %d (%d)\n", src.base, (int)(inst->dst.addr_mode == MODE_REG ? offsetof(m68k_context, dregs) : offsetof(m68k_context, aregs)) + 4 * inst->dst.params.regs.pri, CONTEXT, inst->dst.params.regs.pri); |
350 dst = mov_rrdisp8(dst, src.base, CONTEXT, (inst->dst.addr_mode == MODE_REG ? offsetof(m68k_context, dregs) : offsetof(m68k_context, aregs)) + 4 * inst->dst.params.regs.pri, inst->extra.size); | 350 dst = mov_rrdisp8(dst, src.base, CONTEXT, (inst->dst.addr_mode == MODE_REG ? offsetof(m68k_context, dregs) : offsetof(m68k_context, aregs)) + 4 * inst->dst.params.regs.pri, inst->extra.size); |
351 } else { | 351 } else { |
352 dst = mov_irdisp8(dst, src.disp, CONTEXT, (inst->dst.addr_mode == MODE_REG ? offsetof(m68k_context, dregs) : offsetof(m68k_context, aregs)) + 4 * inst->dst.params.regs.pri, inst->extra.size); | 352 dst = mov_irdisp8(dst, src.disp, CONTEXT, (inst->dst.addr_mode == MODE_REG ? offsetof(m68k_context, dregs) : offsetof(m68k_context, aregs)) + 4 * inst->dst.params.regs.pri, inst->extra.size); |
353 } | 353 } |
354 break; | 354 break; |
456 | 456 |
457 uint8_t * translate_m68k_bsr(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 457 uint8_t * translate_m68k_bsr(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) |
458 { | 458 { |
459 //TODO: Add cycles | 459 //TODO: Add cycles |
460 int32_t disp = inst->src.params.immed; | 460 int32_t disp = inst->src.params.immed; |
461 uint32_t after = inst->address + (inst->variant == VAR_BYTE ? 2 : (inst->variant == VAR_WORD ? 4 : 6)); | 461 uint32_t after = inst->address + 2; |
462 dst = mov_ir(dst, after, SCRATCH1, SZ_D); | 462 dst = mov_ir(dst, after, SCRATCH1, SZ_D); |
463 dst = push_r(dst, SCRATCH1); | 463 dst = push_r(dst, SCRATCH1); |
464 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); | 464 dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); |
465 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); | 465 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); |
466 dst = call(dst, (char *)m68k_write_long_highfirst); | 466 dst = call(dst, (char *)m68k_write_long_highfirst); |
479 | 479 |
480 uint8_t * translate_m68k_bcc(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 480 uint8_t * translate_m68k_bcc(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) |
481 { | 481 { |
482 //TODO: Add cycles | 482 //TODO: Add cycles |
483 int32_t disp = inst->src.params.immed; | 483 int32_t disp = inst->src.params.immed; |
484 uint32_t after = inst->address + (inst->variant == VAR_BYTE ? 2 : (inst->variant == VAR_WORD ? 4 : 6)); | 484 uint32_t after = inst->address + 2; |
485 printf("bcc@%X: after=%X, disp=%X, dest=%X\n", inst->address, after, disp, after+disp); | 485 printf("bcc@%X: after=%X, disp=%X, dest=%X\n", inst->address, after, disp, after+disp); |
486 uint8_t * dest_addr = get_native_address(opts->native_code_map, after + disp); | 486 uint8_t * dest_addr = get_native_address(opts->native_code_map, after + disp); |
487 if (inst->extra.cond == COND_TRUE) { | 487 if (inst->extra.cond == COND_TRUE) { |
488 if (!dest_addr) { | 488 if (!dest_addr) { |
489 opts->deferred = defer_address(opts->deferred, after + disp, dst + 1); | 489 opts->deferred = defer_address(opts->deferred, after + disp, dst + 1); |
553 dst = cmp_rdisp8r(dst, RSP, 8, SCRATCH1, SZ_D); | 553 dst = cmp_rdisp8r(dst, RSP, 8, SCRATCH1, SZ_D); |
554 dst = jcc(dst, CC_NZ, dst+3); | 554 dst = jcc(dst, CC_NZ, dst+3); |
555 dst = retn(dst); | 555 dst = retn(dst); |
556 dst = jmp(dst, (char *)m68k_modified_ret_addr); | 556 dst = jmp(dst, (char *)m68k_modified_ret_addr); |
557 return dst; | 557 return dst; |
558 } | |
559 | |
560 uint8_t * translate_m68k_dbcc(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | |
561 { | |
562 //best case duration | |
563 dst = cycles(dst, 10); | |
564 dst = check_cycles(dst); | |
565 uint8_t * skip_loc = NULL; | |
566 //TODO: Check if COND_TRUE technically valid here even though | |
567 //it's basically a slow NOP | |
568 if (inst->extra.cond != COND_FALSE) { | |
569 uint8_t cond = CC_NZ; | |
570 switch (inst->extra.cond) | |
571 { | |
572 case COND_HIGH: | |
573 cond = CC_Z; | |
574 case COND_LOW_SAME: | |
575 dst = mov_rr(dst, FLAG_Z, SCRATCH1, SZ_B); | |
576 dst = or_rr(dst, FLAG_C, SCRATCH1, SZ_B); | |
577 break; | |
578 case COND_CARRY_CLR: | |
579 cond = CC_Z; | |
580 case COND_CARRY_SET: | |
581 dst = cmp_ir(dst, 0, FLAG_C, SZ_B); | |
582 break; | |
583 case COND_NOT_EQ: | |
584 cond = CC_Z; | |
585 case COND_EQ: | |
586 dst = cmp_ir(dst, 0, FLAG_Z, SZ_B); | |
587 break; | |
588 case COND_OVERF_CLR: | |
589 cond = CC_Z; | |
590 case COND_OVERF_SET: | |
591 dst = cmp_ir(dst, 0, FLAG_V, SZ_B); | |
592 break; | |
593 case COND_PLUS: | |
594 cond = CC_Z; | |
595 case COND_MINUS: | |
596 dst = cmp_ir(dst, 0, FLAG_N, SZ_B); | |
597 break; | |
598 case COND_GREATER_EQ: | |
599 cond = CC_Z; | |
600 case COND_LESS: | |
601 dst = cmp_rr(dst, FLAG_N, FLAG_V, SZ_B); | |
602 break; | |
603 case COND_GREATER: | |
604 cond = CC_Z; | |
605 case COND_LESS_EQ: | |
606 dst = mov_rr(dst, FLAG_V, SCRATCH1, SZ_B); | |
607 dst = xor_rr(dst, FLAG_N, SCRATCH1, SZ_B); | |
608 dst = or_rr(dst, FLAG_Z, SCRATCH1, SZ_B); | |
609 break; | |
610 } | |
611 skip_loc = dst + 1; | |
612 dst = jcc(dst, cond, dst + 2); | |
613 } | |
614 if (opts->dregs[inst->dst.params.regs.pri] >= 0) { | |
615 dst = sub_ir(dst, 1, opts->dregs[inst->dst.params.regs.pri], SZ_W); | |
616 dst = cmp_ir(dst, -1, opts->dregs[inst->dst.params.regs.pri], SZ_W); | |
617 } else { | |
618 dst = sub_irdisp8(dst, 1, CONTEXT, offsetof(m68k_context, dregs) + 4 * inst->dst.params.regs.pri, SZ_W); | |
619 dst = cmp_irdisp8(dst, -1, CONTEXT, offsetof(m68k_context, dregs) + 4 * inst->dst.params.regs.pri, SZ_W); | |
620 } | |
621 uint8_t *loop_end_loc = dst+1; | |
622 dst = jcc(dst, CC_Z, dst+2); | |
623 uint32_t after = inst->address + 2; | |
624 uint8_t * dest_addr = get_native_address(opts->native_code_map, after + inst->src.params.immed); | |
625 if (!dest_addr) { | |
626 opts->deferred = defer_address(opts->deferred, after + inst->src.params.immed, dst + 1); | |
627 //dummy address to be replaced later, make sure it generates a 4-byte displacement | |
628 dest_addr = dst + 256; | |
629 } | |
630 dst = jmp(dst, dest_addr); | |
631 *loop_end_loc = dst - (loop_end_loc+1); | |
632 if (skip_loc) { | |
633 dst = cycles(dst, 2); | |
634 *skip_loc = dst - (skip_loc+1); | |
635 dst = cycles(dst, 2); | |
636 } else { | |
637 dst = cycles(dst, 4); | |
638 } | |
639 dst = check_cycles(dst); | |
558 } | 640 } |
559 | 641 |
560 uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 642 uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) |
561 { | 643 { |
562 map_native_address(opts->native_code_map, inst->address, dst); | 644 map_native_address(opts->native_code_map, inst->address, dst); |
568 return translate_m68k_bsr(dst, inst, opts); | 650 return translate_m68k_bsr(dst, inst, opts); |
569 } else if(inst->op == M68K_BCC) { | 651 } else if(inst->op == M68K_BCC) { |
570 return translate_m68k_bcc(dst, inst, opts); | 652 return translate_m68k_bcc(dst, inst, opts); |
571 } else if(inst->op == M68K_RTS) { | 653 } else if(inst->op == M68K_RTS) { |
572 return translate_m68k_rts(dst, inst, opts); | 654 return translate_m68k_rts(dst, inst, opts); |
655 } else if(inst->op == M68K_DBCC) { | |
656 return translate_m68k_dbcc(dst, inst, opts); | |
573 } | 657 } |
574 x86_ea src_op, dst_op; | 658 x86_ea src_op, dst_op; |
575 if (inst->src.addr_mode != MODE_UNUSED) { | 659 if (inst->src.addr_mode != MODE_UNUSED) { |
576 dst = translate_m68k_src(inst, &src_op, dst, opts); | 660 dst = translate_m68k_src(inst, &src_op, dst, opts); |
577 } | 661 } |