comparison m68k_to_x86.c @ 193:c66e4636f991

Implement support for self-modifying code
author Mike Pavone <pavone@retrodev.com>
date Tue, 15 Jan 2013 00:14:36 -0800
parents 1db07e112bf7
children 811163790e6c
comparison
equal deleted inserted replaced
192:1db07e112bf7 193:c66e4636f991
42 void m68k_modified_ret_addr(); 42 void m68k_modified_ret_addr();
43 void m68k_native_addr(); 43 void m68k_native_addr();
44 void m68k_native_addr_and_sync(); 44 void m68k_native_addr_and_sync();
45 void m68k_trap(); 45 void m68k_trap();
46 void m68k_invalid(); 46 void m68k_invalid();
47 void m68k_retrans_stub();
47 void set_sr(); 48 void set_sr();
48 void set_ccr(); 49 void set_ccr();
49 void get_sr(); 50 void get_sr();
50 void do_sync(); 51 void do_sync();
51 void m68k_start_context(uint8_t * addr, m68k_context * context); 52 void m68k_start_context(uint8_t * addr, m68k_context * context);
677 } 678 }
678 679
679 uint8_t * get_native_address(native_map_slot * native_code_map, uint32_t address) 680 uint8_t * get_native_address(native_map_slot * native_code_map, uint32_t address)
680 { 681 {
681 address &= 0xFFFFFF; 682 address &= 0xFFFFFF;
682 if (address > 0x400000) {
683 printf("get_native_address: %X\n", address);
684 }
685 address /= 2; 683 address /= 2;
686 uint32_t chunk = address / NATIVE_CHUNK_SIZE; 684 uint32_t chunk = address / NATIVE_CHUNK_SIZE;
687 if (!native_code_map[chunk].base) { 685 if (!native_code_map[chunk].base) {
688 return NULL; 686 return NULL;
689 } 687 }
690 uint32_t offset = address % NATIVE_CHUNK_SIZE; 688 uint32_t offset = address % NATIVE_CHUNK_SIZE;
689 if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET || native_code_map[chunk].offsets[offset] == EXTENSION_WORD) {
690 return NULL;
691 }
692 return native_code_map[chunk].base + native_code_map[chunk].offsets[offset];
693 }
694
695 uint32_t get_instruction_start(native_map_slot * native_code_map, uint32_t address)
696 {
697 address &= 0xFFFFFF;
698 address /= 2;
699 uint32_t chunk = address / NATIVE_CHUNK_SIZE;
700 if (!native_code_map[chunk].base) {
701 return 0;
702 }
703 uint32_t offset = address % NATIVE_CHUNK_SIZE;
691 if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET) { 704 if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET) {
692 return NULL; 705 return 0;
693 } 706 }
694 return native_code_map[chunk].base + native_code_map[chunk].offsets[offset]; 707 while (native_code_map[chunk].offsets[offset] == EXTENSION_WORD) {
708 --address;
709 chunk = address / NATIVE_CHUNK_SIZE;
710 offset = address % NATIVE_CHUNK_SIZE;
711 }
712 return address*2;
695 } 713 }
696 714
697 deferred_addr * defer_address(deferred_addr * old_head, uint32_t address, uint8_t *dest) 715 deferred_addr * defer_address(deferred_addr * old_head, uint32_t address, uint8_t *dest)
698 { 716 {
699 deferred_addr * new_head = malloc(sizeof(deferred_addr)); 717 deferred_addr * new_head = malloc(sizeof(deferred_addr));
753 native_code_map[chunk].offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE); 771 native_code_map[chunk].offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE);
754 memset(native_code_map[chunk].offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE); 772 memset(native_code_map[chunk].offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE);
755 } 773 }
756 uint32_t offset = address % NATIVE_CHUNK_SIZE; 774 uint32_t offset = address % NATIVE_CHUNK_SIZE;
757 native_code_map[chunk].offsets[offset] = native_addr-native_code_map[chunk].base; 775 native_code_map[chunk].offsets[offset] = native_addr-native_code_map[chunk].base;
776 for(address++,size-=2; size; address++,size-=2) {
777 chunk = address / NATIVE_CHUNK_SIZE;
778 offset = address % NATIVE_CHUNK_SIZE;
779 if (!native_code_map[chunk].base) {
780 native_code_map[chunk].base = native_addr;
781 native_code_map[chunk].offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE);
782 memset(native_code_map[chunk].offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE);
783 }
784 native_code_map[chunk].offsets[offset] = EXTENSION_WORD;
785 }
786 }
787
788 uint8_t get_native_inst_size(x86_68k_options * opts, uint32_t address)
789 {
790 if (address < 0xE00000) {
791 return 0;
792 }
793 uint32_t slot = (address & 0xFFFF)/1024;
794 return opts->ram_inst_sizes[slot][((address & 0xFFFF)/2)%512];
758 } 795 }
759 796
760 uint8_t * translate_m68k_move(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) 797 uint8_t * translate_m68k_move(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
761 { 798 {
762 int8_t reg, flags_reg, sec_reg; 799 int8_t reg, flags_reg, sec_reg;
3609 printf("attempt to translate non-memory address: %X\n", address); 3646 printf("attempt to translate non-memory address: %X\n", address);
3610 exit(1); 3647 exit(1);
3611 } 3648 }
3612 do { 3649 do {
3613 do { 3650 do {
3614 if (dst_end-dst < 128) { 3651 if (dst_end-dst < MAX_NATIVE_SIZE) {
3615 if (dst_end-dst < 5) { 3652 if (dst_end-dst < 5) {
3616 puts("out of code memory, not enough space for jmp to next chunk"); 3653 puts("out of code memory, not enough space for jmp to next chunk");
3617 exit(1); 3654 exit(1);
3618 } 3655 }
3619 size_t size = 1024*1024; 3656 size_t size = 1024*1024;
3669 if (!ret) { 3706 if (!ret) {
3670 translate_m68k_stream(address, context); 3707 translate_m68k_stream(address, context);
3671 ret = get_native_address(context->native_code_map, address); 3708 ret = get_native_address(context->native_code_map, address);
3672 } 3709 }
3673 return ret; 3710 return ret;
3711 }
3712
3713 void * m68k_retranslate_inst(uint32_t address, m68k_context * context)
3714 {
3715 x86_68k_options * opts = context->options;
3716 uint8_t orig_size = get_native_inst_size(opts, address);
3717 uint8_t * orig_start = get_native_address(context->native_code_map, address);
3718 uint32_t orig = address;
3719 address &= 0xFFFF;
3720 uint8_t * dst = opts->cur_code;
3721 uint8_t * dst_end = opts->code_end;
3722 uint16_t *after, *inst = context->mem_pointers[1] + address/2;
3723 m68kinst instbuf;
3724 after = m68k_decode(inst, &instbuf, orig);
3725 if (orig_size != MAX_NATIVE_SIZE) {
3726 if (dst_end - dst < 128) {
3727 size_t size = 1024*1024;
3728 dst = alloc_code(&size);
3729 opts->code_end = dst_end = dst + size;
3730 opts->cur_code = dst;
3731 }
3732 uint8_t * native_end = translate_m68k(dst, &instbuf, opts);
3733 if ((native_end - dst) <= orig_size) {
3734 native_end = translate_m68k(orig_start, &instbuf, opts);
3735 while (native_end < orig_start + orig_size) {
3736 *(native_end++) = 0x90; //NOP
3737 }
3738 return orig_start;
3739 } else {
3740 map_native_address(context, instbuf.address, dst, (after-inst)*2, MAX_NATIVE_SIZE);
3741 opts->code_end = dst+MAX_NATIVE_SIZE;
3742 if (instbuf.op != M68K_RTS && instbuf.op != M68K_RTE && instbuf.op != M68K_RTR && instbuf.op != M68K_JMP && (instbuf.op != M68K_BCC || instbuf.extra.cond != COND_TRUE)) {
3743 jmp(native_end, get_native_address(context->native_code_map, address + (after-inst)*2));
3744 }
3745 return dst;
3746 }
3747 } else {
3748 dst = translate_m68k(orig_start, &instbuf, opts);
3749 if (instbuf.op != M68K_RTS && instbuf.op != M68K_RTE && instbuf.op != M68K_RTR && instbuf.op != M68K_JMP && (instbuf.op != M68K_BCC || instbuf.extra.cond != COND_TRUE)) {
3750 dst = jmp(dst, get_native_address(context->native_code_map, address + (after-inst)*2));
3751 }
3752 return orig_start;
3753 }
3754 }
3755
3756 m68k_context * m68k_handle_code_write(uint32_t address, m68k_context * context)
3757 {
3758 uint32_t inst_start = get_instruction_start(context->native_code_map, address | 0xFF0000);
3759 if (inst_start) {
3760 uint8_t * dst = get_native_address(context->native_code_map, inst_start);
3761 dst = mov_ir(dst, inst_start, SCRATCH2, SZ_D);
3762 dst = jmp(dst, (uint8_t *)m68k_retrans_stub);
3763 }
3764 return context;
3674 } 3765 }
3675 3766
3676 void insert_breakpoint(m68k_context * context, uint32_t address, uint8_t * bp_handler) 3767 void insert_breakpoint(m68k_context * context, uint32_t address, uint8_t * bp_handler)
3677 { 3768 {
3678 static uint8_t * bp_stub = NULL; 3769 static uint8_t * bp_stub = NULL;
3758 opts->deferred = NULL; 3849 opts->deferred = NULL;
3759 size_t size = 1024 * 1024; 3850 size_t size = 1024 * 1024;
3760 opts->cur_code = alloc_code(&size); 3851 opts->cur_code = alloc_code(&size);
3761 opts->code_end = opts->cur_code + size; 3852 opts->code_end = opts->cur_code + size;
3762 opts->ram_inst_sizes = malloc(sizeof(uint8_t *) * 64); 3853 opts->ram_inst_sizes = malloc(sizeof(uint8_t *) * 64);
3854 memset(opts->ram_inst_sizes, 0, sizeof(uint8_t *) * 64);
3763 } 3855 }
3764 3856
3765 void init_68k_context(m68k_context * context, native_map_slot * native_code_map, void * opts) 3857 void init_68k_context(m68k_context * context, native_map_slot * native_code_map, void * opts)
3766 { 3858 {
3767 memset(context, 0, sizeof(m68k_context)); 3859 memset(context, 0, sizeof(m68k_context));