Mercurial > repos > blastem
comparison m68k_core_x86.c @ 667:30ccf56842d6
All cycle counters are now based off the master clock. This seems to have messed up Z80 interrupt timing (music in Sonic 2 is too slow for instance), but things are generally working
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 03 Jan 2015 16:08:23 -0800 |
parents | d0943769353b |
children | 7ed1dbb48f61 |
comparison
equal
deleted
inserted
replaced
666:b68039895627 | 667:30ccf56842d6 |
---|---|
1010 if (inst->src.addr_mode == MODE_UNUSED) { | 1010 if (inst->src.addr_mode == MODE_UNUSED) { |
1011 cycles(&opts->gen, BUS); | 1011 cycles(&opts->gen, BUS); |
1012 //Memory shift | 1012 //Memory shift |
1013 shift_ir(code, 1, dst_op->base, SZ_W); | 1013 shift_ir(code, 1, dst_op->base, SZ_W); |
1014 } else { | 1014 } else { |
1015 cycles(&opts->gen, inst->extra.size == OPSIZE_LONG ? 8 : 6); | |
1016 if (src_op->mode == MODE_IMMED) { | 1015 if (src_op->mode == MODE_IMMED) { |
1016 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + 2 * src_op->disp); | |
1017 if (src_op->disp != 1 && inst->op == M68K_ASL) { | 1017 if (src_op->disp != 1 && inst->op == M68K_ASL) { |
1018 set_flag(opts, 0, FLAG_V); | 1018 set_flag(opts, 0, FLAG_V); |
1019 for (int i = 0; i < src_op->disp; i++) { | 1019 for (int i = 0; i < src_op->disp; i++) { |
1020 if (dst_op->mode == MODE_REG_DIRECT) { | 1020 if (dst_op->mode == MODE_REG_DIRECT) { |
1021 shift_ir(code, 1, dst_op->base, inst->extra.size); | 1021 shift_ir(code, 1, dst_op->base, inst->extra.size); |
1035 shift_irdisp(code, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); | 1035 shift_irdisp(code, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); |
1036 } | 1036 } |
1037 set_flag_cond(opts, CC_O, FLAG_V); | 1037 set_flag_cond(opts, CC_O, FLAG_V); |
1038 } | 1038 } |
1039 } else { | 1039 } else { |
1040 cycles(&opts->gen, inst->extra.size == OPSIZE_LONG ? 8 : 6); | |
1040 if (src_op->base != RCX) { | 1041 if (src_op->base != RCX) { |
1041 if (src_op->mode == MODE_REG_DIRECT) { | 1042 if (src_op->mode == MODE_REG_DIRECT) { |
1042 mov_rr(code, src_op->base, RCX, SZ_B); | 1043 mov_rr(code, src_op->base, RCX, SZ_B); |
1043 } else { | 1044 } else { |
1044 mov_rdispr(code, src_op->base, src_op->disp, RCX, SZ_B); | 1045 mov_rdispr(code, src_op->base, src_op->disp, RCX, SZ_B); |
1064 } | 1065 } |
1065 z_off = code->cur + 1; | 1066 z_off = code->cur + 1; |
1066 jmp(code, code->cur + 2); | 1067 jmp(code, code->cur + 2); |
1067 *nz_off = code->cur - (nz_off + 1); | 1068 *nz_off = code->cur - (nz_off + 1); |
1068 //add 2 cycles for every bit shifted | 1069 //add 2 cycles for every bit shifted |
1069 add_rr(code, RCX, opts->gen.cycles, SZ_D); | 1070 mov_ir(code, 2 * opts->gen.clock_divider, opts->gen.scratch2, SZ_D); |
1070 add_rr(code, RCX, opts->gen.cycles, SZ_D); | 1071 imul_rr(code, RCX, opts->gen.scratch2, SZ_D); |
1072 add_rr(code, opts->gen.scratch2, opts->gen.cycles, SZ_D); | |
1071 if (inst->op == M68K_ASL) { | 1073 if (inst->op == M68K_ASL) { |
1072 //ASL has Overflow flag behavior that depends on all of the bits shifted through the MSB | 1074 //ASL has Overflow flag behavior that depends on all of the bits shifted through the MSB |
1073 //Easiest way to deal with this is to shift one bit at a time | 1075 //Easiest way to deal with this is to shift one bit at a time |
1074 set_flag(opts, 0, FLAG_V); | 1076 set_flag(opts, 0, FLAG_V); |
1075 check_alloc_code(code, 5*MAX_INST_LEN); | 1077 check_alloc_code(code, 5*MAX_INST_LEN); |
1863 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_B); | 1865 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_B); |
1864 } | 1866 } |
1865 and_ir(code, 63, opts->gen.scratch1, SZ_D); | 1867 and_ir(code, 63, opts->gen.scratch1, SZ_D); |
1866 code_ptr zero_off = code->cur + 1; | 1868 code_ptr zero_off = code->cur + 1; |
1867 jcc(code, CC_Z, code->cur + 2); | 1869 jcc(code, CC_Z, code->cur + 2); |
1868 add_rr(code, opts->gen.scratch1, opts->gen.cycles, SZ_D); | 1870 //add 2 cycles for every bit shifted |
1869 add_rr(code, opts->gen.scratch1, opts->gen.cycles, SZ_D); | 1871 mov_ir(code, 2 * opts->gen.clock_divider, opts->gen.scratch2, SZ_D); |
1872 imul_rr(code, RCX, opts->gen.scratch2, SZ_D); | |
1873 add_rr(code, opts->gen.scratch2, opts->gen.cycles, SZ_D); | |
1870 cmp_ir(code, 32, opts->gen.scratch1, SZ_B); | 1874 cmp_ir(code, 32, opts->gen.scratch1, SZ_B); |
1871 code_ptr norm_off = code->cur + 1; | 1875 code_ptr norm_off = code->cur + 1; |
1872 jcc(code, CC_L, code->cur + 2); | 1876 jcc(code, CC_L, code->cur + 2); |
1873 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) { | 1877 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) { |
1874 flag_to_carry(opts, FLAG_X); | 1878 flag_to_carry(opts, FLAG_X); |
2184 } else { | 2188 } else { |
2185 call(&native, bp_stub); | 2189 call(&native, bp_stub); |
2186 } | 2190 } |
2187 } | 2191 } |
2188 | 2192 |
2189 void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks) | 2193 void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks, uint32_t clock_divider) |
2190 { | 2194 { |
2191 memset(opts, 0, sizeof(*opts)); | 2195 memset(opts, 0, sizeof(*opts)); |
2192 opts->gen.memmap = memmap; | 2196 opts->gen.memmap = memmap; |
2193 opts->gen.memmap_chunks = num_chunks; | 2197 opts->gen.memmap_chunks = num_chunks; |
2194 opts->gen.address_size = SZ_D; | 2198 opts->gen.address_size = SZ_D; |
2195 opts->gen.address_mask = 0xFFFFFF; | 2199 opts->gen.address_mask = 0xFFFFFF; |
2196 opts->gen.byte_swap = 1; | 2200 opts->gen.byte_swap = 1; |
2197 opts->gen.max_address = 0x1000000; | 2201 opts->gen.max_address = 0x1000000; |
2198 opts->gen.bus_cycles = BUS; | 2202 opts->gen.bus_cycles = BUS; |
2203 opts->gen.clock_divider = clock_divider; | |
2199 opts->gen.mem_ptr_off = offsetof(m68k_context, mem_pointers); | 2204 opts->gen.mem_ptr_off = offsetof(m68k_context, mem_pointers); |
2200 opts->gen.ram_flags_off = offsetof(m68k_context, ram_code_flags); | 2205 opts->gen.ram_flags_off = offsetof(m68k_context, ram_code_flags); |
2201 opts->gen.ram_flags_shift = 11; | 2206 opts->gen.ram_flags_shift = 11; |
2202 for (int i = 0; i < 8; i++) | 2207 for (int i = 0; i < 8; i++) |
2203 { | 2208 { |
2306 retn(code); | 2311 retn(code); |
2307 | 2312 |
2308 opts->native_addr_and_sync = code->cur; | 2313 opts->native_addr_and_sync = code->cur; |
2309 call(code, opts->gen.save_context); | 2314 call(code, opts->gen.save_context); |
2310 push_r(code, opts->gen.scratch1); | 2315 push_r(code, opts->gen.scratch1); |
2311 | 2316 |
2312 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_D); | 2317 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_D); |
2313 call_args_abi(code, (code_ptr)sync_components, 2, opts->gen.context_reg, opts->gen.scratch1); | 2318 call_args_abi(code, (code_ptr)sync_components, 2, opts->gen.context_reg, opts->gen.scratch1); |
2314 pop_r(code, RSI); //restore saved address from opts->gen.scratch1 | 2319 pop_r(code, RSI); //restore saved address from opts->gen.scratch1 |
2315 push_r(code, RAX); //save context pointer for later | 2320 push_r(code, RAX); //save context pointer for later |
2316 call_args(code, (code_ptr)get_native_address_trans, 2, RAX, RSI); | 2321 call_args(code, (code_ptr)get_native_address_trans, 2, RAX, RSI); |