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 }