comparison m68k_to_x86.c @ 544:8a26567852b7

Generate native_addr and native_addr_and_sync at runtime so they can use the generated save/load_context functions
author Michael Pavone <pavone@retrodev.com>
date Sun, 16 Feb 2014 19:21:39 -0800
parents 915a1cb98bac
children 67cf0ce57d8d
comparison
equal deleted inserted replaced
543:915a1cb98bac 544:8a26567852b7
29 char disasm_buf[1024]; 29 char disasm_buf[1024];
30 30
31 m68k_context * sync_components(m68k_context * context, uint32_t address); 31 m68k_context * sync_components(m68k_context * context, uint32_t address);
32 32
33 void handle_cycle_limit(); 33 void handle_cycle_limit();
34 void m68k_native_addr();
35 void m68k_native_addr_and_sync();
36 void m68k_invalid(); 34 void m68k_invalid();
37 void set_sr(); 35 void set_sr();
38 void set_ccr(); 36 void set_ccr();
39 void get_sr(); 37 void get_sr();
40 void do_sync(); 38 void do_sync();
1924 if (opts->aregs[inst->src.params.regs.pri] >= 0) { 1922 if (opts->aregs[inst->src.params.regs.pri] >= 0) {
1925 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); 1923 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D);
1926 } else { 1924 } else {
1927 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D); 1925 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D);
1928 } 1926 }
1929 dst = call(dst, (uint8_t *)m68k_native_addr); 1927 dst = call(dst, opts->native_addr);
1930 dst = jmp_r(dst, SCRATCH1); 1928 dst = jmp_r(dst, SCRATCH1);
1931 break; 1929 break;
1932 case MODE_AREG_INDEX_DISP8: 1930 case MODE_AREG_INDEX_DISP8:
1933 dst = cycles(dst, BUS*3);//TODO: CHeck that this is correct 1931 dst = cycles(dst, BUS*3);//TODO: CHeck that this is correct
1934 if (opts->aregs[inst->src.params.regs.pri] >= 0) { 1932 if (opts->aregs[inst->src.params.regs.pri] >= 0) {
1970 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D); 1968 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D);
1971 } 1969 }
1972 if (inst->src.params.regs.displacement) { 1970 if (inst->src.params.regs.displacement) {
1973 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); 1971 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D);
1974 } 1972 }
1975 dst = call(dst, (uint8_t *)m68k_native_addr); 1973 dst = call(dst, opts->native_addr);
1976 dst = jmp_r(dst, SCRATCH1); 1974 dst = jmp_r(dst, SCRATCH1);
1977 break; 1975 break;
1978 case MODE_PC_DISPLACE: 1976 case MODE_PC_DISPLACE:
1979 dst = cycles(dst, 10); 1977 dst = cycles(dst, 10);
1980 m68k_addr = inst->src.params.regs.displacement + inst->address + 2; 1978 m68k_addr = inst->src.params.regs.displacement + inst->address + 2;
1986 dest_addr = dst + 256; 1984 dest_addr = dst + 256;
1987 } 1985 }
1988 dst = jmp(dst, dest_addr); 1986 dst = jmp(dst, dest_addr);
1989 } else { 1987 } else {
1990 dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D); 1988 dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D);
1991 dst = call(dst, (uint8_t *)m68k_native_addr); 1989 dst = call(dst, opts->native_addr);
1992 dst = jmp_r(dst, SCRATCH1); 1990 dst = jmp_r(dst, SCRATCH1);
1993 } 1991 }
1994 break; 1992 break;
1995 case MODE_PC_INDEX_DISP8: 1993 case MODE_PC_INDEX_DISP8:
1996 dst = cycles(dst, BUS*3);//TODO: CHeck that this is correct 1994 dst = cycles(dst, BUS*3);//TODO: CHeck that this is correct
2027 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D); 2025 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D);
2028 } 2026 }
2029 if (inst->src.params.regs.displacement) { 2027 if (inst->src.params.regs.displacement) {
2030 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); 2028 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D);
2031 } 2029 }
2032 dst = call(dst, (uint8_t *)m68k_native_addr); 2030 dst = call(dst, opts->native_addr);
2033 dst = jmp_r(dst, SCRATCH1); 2031 dst = jmp_r(dst, SCRATCH1);
2034 break; 2032 break;
2035 case MODE_ABSOLUTE: 2033 case MODE_ABSOLUTE:
2036 case MODE_ABSOLUTE_SHORT: 2034 case MODE_ABSOLUTE_SHORT:
2037 dst = cycles(dst, inst->src.addr_mode == MODE_ABSOLUTE ? 12 : 10); 2035 dst = cycles(dst, inst->src.addr_mode == MODE_ABSOLUTE ? 12 : 10);
2044 dest_addr = dst + 256; 2042 dest_addr = dst + 256;
2045 } 2043 }
2046 dst = jmp(dst, dest_addr); 2044 dst = jmp(dst, dest_addr);
2047 } else { 2045 } else {
2048 dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D); 2046 dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D);
2049 dst = call(dst, (uint8_t *)m68k_native_addr); 2047 dst = call(dst, opts->native_addr);
2050 dst = jmp_r(dst, SCRATCH1); 2048 dst = jmp_r(dst, SCRATCH1);
2051 } 2049 }
2052 break; 2050 break;
2053 default: 2051 default:
2054 m68k_disasm(inst, disasm_buf); 2052 m68k_disasm(inst, disasm_buf);
2074 if (opts->aregs[inst->src.params.regs.pri] >= 0) { 2072 if (opts->aregs[inst->src.params.regs.pri] >= 0) {
2075 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); 2073 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D);
2076 } else { 2074 } else {
2077 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D); 2075 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D);
2078 } 2076 }
2079 dst = call(dst, (uint8_t *)m68k_native_addr); 2077 dst = call(dst, opts->native_addr);
2080 dst = jmp_r(dst, SCRATCH1); 2078 dst = jmp_r(dst, SCRATCH1);
2081 break; 2079 break;
2082 case MODE_AREG_DISPLACE: 2080 case MODE_AREG_DISPLACE:
2083 dst = cycles(dst, BUS*2); 2081 dst = cycles(dst, BUS*2);
2084 dst = mov_ir(dst, inst->address + 4, SCRATCH1, SZ_D); 2082 dst = mov_ir(dst, inst->address + 4, SCRATCH1, SZ_D);
2089 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D); 2087 dst = mov_rr(dst, opts->aregs[inst->src.params.regs.pri], SCRATCH1, SZ_D);
2090 } else { 2088 } else {
2091 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D); 2089 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + 4 * inst->src.params.regs.pri, SCRATCH1, SZ_D);
2092 } 2090 }
2093 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); 2091 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D);
2094 dst = call(dst, (uint8_t *)m68k_native_addr); 2092 dst = call(dst, opts->native_addr);
2095 dst = jmp_r(dst, SCRATCH1); 2093 dst = jmp_r(dst, SCRATCH1);
2096 break; 2094 break;
2097 case MODE_AREG_INDEX_DISP8: 2095 case MODE_AREG_INDEX_DISP8:
2098 dst = cycles(dst, BUS*3);//TODO: CHeck that this is correct 2096 dst = cycles(dst, BUS*3);//TODO: CHeck that this is correct
2099 dst = mov_ir(dst, inst->address + 4, SCRATCH1, SZ_D); 2097 dst = mov_ir(dst, inst->address + 4, SCRATCH1, SZ_D);
2137 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D); 2135 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D);
2138 } 2136 }
2139 if (inst->src.params.regs.displacement) { 2137 if (inst->src.params.regs.displacement) {
2140 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); 2138 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D);
2141 } 2139 }
2142 dst = call(dst, (uint8_t *)m68k_native_addr); 2140 dst = call(dst, opts->native_addr);
2143 dst = jmp_r(dst, SCRATCH1); 2141 dst = jmp_r(dst, SCRATCH1);
2144 break; 2142 break;
2145 case MODE_PC_DISPLACE: 2143 case MODE_PC_DISPLACE:
2146 //TODO: Add cycles in the right place relative to pushing the return address on the stack 2144 //TODO: Add cycles in the right place relative to pushing the return address on the stack
2147 dst = cycles(dst, 10); 2145 dst = cycles(dst, 10);
2158 dest_addr = dst + 256; 2156 dest_addr = dst + 256;
2159 } 2157 }
2160 dst = jmp(dst, dest_addr); 2158 dst = jmp(dst, dest_addr);
2161 } else { 2159 } else {
2162 dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D); 2160 dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D);
2163 dst = call(dst, (uint8_t *)m68k_native_addr); 2161 dst = call(dst, opts->native_addr);
2164 dst = jmp_r(dst, SCRATCH1); 2162 dst = jmp_r(dst, SCRATCH1);
2165 } 2163 }
2166 break; 2164 break;
2167 case MODE_PC_INDEX_DISP8: 2165 case MODE_PC_INDEX_DISP8:
2168 dst = cycles(dst, BUS*3);//TODO: CHeck that this is correct 2166 dst = cycles(dst, BUS*3);//TODO: CHeck that this is correct
2203 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D); 2201 dst = add_rr(dst, SCRATCH2, SCRATCH1, SZ_D);
2204 } 2202 }
2205 if (inst->src.params.regs.displacement) { 2203 if (inst->src.params.regs.displacement) {
2206 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D); 2204 dst = add_ir(dst, inst->src.params.regs.displacement, SCRATCH1, SZ_D);
2207 } 2205 }
2208 dst = call(dst, (uint8_t *)m68k_native_addr); 2206 dst = call(dst, opts->native_addr);
2209 dst = jmp_r(dst, SCRATCH1); 2207 dst = jmp_r(dst, SCRATCH1);
2210 break; 2208 break;
2211 case MODE_ABSOLUTE: 2209 case MODE_ABSOLUTE:
2212 case MODE_ABSOLUTE_SHORT: 2210 case MODE_ABSOLUTE_SHORT:
2213 //TODO: Add cycles in the right place relative to pushing the return address on the stack 2211 //TODO: Add cycles in the right place relative to pushing the return address on the stack
2225 dest_addr = dst + 256; 2223 dest_addr = dst + 256;
2226 } 2224 }
2227 dst = jmp(dst, dest_addr); 2225 dst = jmp(dst, dest_addr);
2228 } else { 2226 } else {
2229 dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D); 2227 dst = mov_ir(dst, m68k_addr, SCRATCH1, SZ_D);
2230 dst = call(dst, (uint8_t *)m68k_native_addr); 2228 dst = call(dst, opts->native_addr);
2231 dst = jmp_r(dst, SCRATCH1); 2229 dst = jmp_r(dst, SCRATCH1);
2232 } 2230 }
2233 break; 2231 break;
2234 default: 2232 default:
2235 m68k_disasm(inst, disasm_buf); 2233 m68k_disasm(inst, disasm_buf);
2243 { 2241 {
2244 //TODO: Add cycles 2242 //TODO: Add cycles
2245 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); 2243 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D);
2246 dst = add_ir(dst, 4, opts->aregs[7], SZ_D); 2244 dst = add_ir(dst, 4, opts->aregs[7], SZ_D);
2247 dst = call(dst, opts->read_32); 2245 dst = call(dst, opts->read_32);
2248 dst = call(dst, (uint8_t *)m68k_native_addr); 2246 dst = call(dst, opts->native_addr);
2249 dst = jmp_r(dst, SCRATCH1); 2247 dst = jmp_r(dst, SCRATCH1);
2250 return dst; 2248 return dst;
2251 } 2249 }
2252 2250
2253 uint8_t * translate_m68k_dbcc(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) 2251 uint8_t * translate_m68k_dbcc(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
3646 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D); 3644 dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D);
3647 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); 3645 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D);
3648 dst = mov_rrdisp8(dst, SCRATCH2, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D); 3646 dst = mov_rrdisp8(dst, SCRATCH2, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D);
3649 *end_off = dst - (end_off+1); 3647 *end_off = dst - (end_off+1);
3650 //Get native address, sync components, recalculate integer points and jump to returned address 3648 //Get native address, sync components, recalculate integer points and jump to returned address
3651 dst = call(dst, (uint8_t *)m68k_native_addr_and_sync); 3649 dst = call(dst, opts->native_addr_and_sync);
3652 dst = jmp_r(dst, SCRATCH1); 3650 dst = jmp_r(dst, SCRATCH1);
3653 break; 3651 break;
3654 case M68K_RTR: 3652 case M68K_RTR:
3655 //Read saved CCR 3653 //Read saved CCR
3656 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); 3654 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D);
3660 //Read saved PC 3658 //Read saved PC
3661 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); 3659 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D);
3662 dst = call(dst, opts->read_32); 3660 dst = call(dst, opts->read_32);
3663 dst = add_ir(dst, 4, opts->aregs[7], SZ_D); 3661 dst = add_ir(dst, 4, opts->aregs[7], SZ_D);
3664 //Get native address and jump to it 3662 //Get native address and jump to it
3665 dst = call(dst, (uint8_t *)m68k_native_addr); 3663 dst = call(dst, opts->native_addr);
3666 dst = jmp_r(dst, SCRATCH1); 3664 dst = jmp_r(dst, SCRATCH1);
3667 break; 3665 break;
3668 case M68K_SBCD: 3666 case M68K_SBCD:
3669 if (src_op.base != SCRATCH2) { 3667 if (src_op.base != SCRATCH2) {
3670 if (src_op.mode == MODE_REG_DIRECT) { 3668 if (src_op.mode == MODE_REG_DIRECT) {
4383 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, current_cycle), CYCLES, SZ_D); 4381 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, current_cycle), CYCLES, SZ_D);
4384 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, target_cycle), LIMIT, SZ_D); 4382 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, target_cycle), LIMIT, SZ_D);
4385 dst = retn(dst); 4383 dst = retn(dst);
4386 4384
4387 opts->start_context = (start_fun)dst; 4385 opts->start_context = (start_fun)dst;
4386 //save callee save registers
4388 dst = push_r(dst, RBP); 4387 dst = push_r(dst, RBP);
4389 dst = push_r(dst, R12); 4388 dst = push_r(dst, R12);
4390 dst = push_r(dst, R13); 4389 dst = push_r(dst, R13);
4391 dst = push_r(dst, R14); 4390 dst = push_r(dst, R14);
4392 dst = push_r(dst, R15); 4391 dst = push_r(dst, R15);
4393 dst = call(dst, opts->load_context); 4392 dst = call(dst, opts->load_context);
4394 dst = call_r(dst, RDI); 4393 dst = call_r(dst, RDI);
4395 dst = call(dst, opts->save_context); 4394 dst = call(dst, opts->save_context);
4395 //restore callee save registers
4396 dst = pop_r(dst, R15); 4396 dst = pop_r(dst, R15);
4397 dst = pop_r(dst, R14); 4397 dst = pop_r(dst, R14);
4398 dst = pop_r(dst, R13); 4398 dst = pop_r(dst, R13);
4399 dst = pop_r(dst, R12); 4399 dst = pop_r(dst, R12);
4400 dst = pop_r(dst, RBP); 4400 dst = pop_r(dst, RBP);
4401 dst = retn(dst);
4402
4403 opts->native_addr = dst;
4404 dst = call(dst, opts->save_context);
4405 dst = push_r(dst, CONTEXT);
4406 dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); //move context to 1st arg reg
4407 dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); //move address to 2nd arg reg
4408 dst = call(dst, (uint8_t *)get_native_address_trans);
4409 dst = mov_rr(dst, RAX, SCRATCH1, SZ_Q); //move result to scratch reg
4410 dst = pop_r(dst, CONTEXT);
4411 dst = call(dst, opts->load_context);
4412 dst = retn(dst);
4413
4414 opts->native_addr_and_sync = dst;
4415 dst = call(dst, opts->save_context);
4416 dst = push_r(dst, SCRATCH1);
4417 dst = mov_rr(dst, CONTEXT, RDI, SZ_Q);
4418 dst = xor_rr(dst, RSI, RSI, SZ_D);
4419 dst = test_ir(dst, 8, RSP, SZ_Q); //check stack alignment
4420 uint8_t * do_adjust_rsp = dst+1;
4421 dst = jcc(dst, CC_NZ, dst+2);
4422 dst = call(dst, (uint8_t *)sync_components);
4423 uint8_t * no_adjust_rsp = dst+1;
4424 dst = jmp(dst, dst+2);
4425 *do_adjust_rsp = dst - (do_adjust_rsp+1);
4426 dst = sub_ir(dst, 8, RSP, SZ_Q);
4427 dst = call(dst, (uint8_t *)sync_components);
4428 dst = add_ir(dst, 8, RSP, SZ_Q);
4429 *no_adjust_rsp = dst - (no_adjust_rsp+1);
4430 dst = pop_r(dst, RSI);
4431 dst = push_r(dst, RAX);
4432 dst = mov_rr(dst, RAX, RDI, SZ_Q);
4433 dst = call(dst, (uint8_t *)get_native_address_trans);
4434 dst = mov_rr(dst, RAX, SCRATCH1, SZ_Q); //move result to scratch reg
4435 dst = pop_r(dst, CONTEXT);
4436 dst = call(dst, opts->load_context);
4401 dst = retn(dst); 4437 dst = retn(dst);
4402 4438
4403 opts->cur_code = dst; 4439 opts->cur_code = dst;
4404 4440
4405 opts->read_16 = gen_mem_fun(opts, memmap, num_chunks, READ_16); 4441 opts->read_16 = gen_mem_fun(opts, memmap, num_chunks, READ_16);
4497 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_num), SCRATCH1, SZ_D); 4533 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, int_num), SCRATCH1, SZ_D);
4498 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, int_ack), SZ_W); 4534 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, int_ack), SZ_W);
4499 dst = shl_ir(dst, 2, SCRATCH1, SZ_D); 4535 dst = shl_ir(dst, 2, SCRATCH1, SZ_D);
4500 dst = add_ir(dst, 0x60, SCRATCH1, SZ_D); 4536 dst = add_ir(dst, 0x60, SCRATCH1, SZ_D);
4501 dst = call(dst, opts->read_32); 4537 dst = call(dst, opts->read_32);
4502 dst = call(dst, (uint8_t *)m68k_native_addr_and_sync); 4538 dst = call(dst, opts->native_addr_and_sync);
4503 dst = cycles(dst, 24); 4539 dst = cycles(dst, 24);
4504 //discard function return address 4540 //discard function return address
4505 dst = pop_r(dst, SCRATCH2); 4541 dst = pop_r(dst, SCRATCH2);
4506 dst = jmp_r(dst, SCRATCH1); 4542 dst = jmp_r(dst, SCRATCH1);
4507 4543
4528 dst = or_irdisp8(dst, 0x20, CONTEXT, offsetof(m68k_context, status), SZ_B); 4564 dst = or_irdisp8(dst, 0x20, CONTEXT, offsetof(m68k_context, status), SZ_B);
4529 //calculate vector address 4565 //calculate vector address
4530 dst = pop_r(dst, SCRATCH1); 4566 dst = pop_r(dst, SCRATCH1);
4531 dst = shl_ir(dst, 2, SCRATCH1, SZ_D); 4567 dst = shl_ir(dst, 2, SCRATCH1, SZ_D);
4532 dst = call(dst, opts->read_32); 4568 dst = call(dst, opts->read_32);
4533 dst = call(dst, (uint8_t *)m68k_native_addr_and_sync); 4569 dst = call(dst, opts->native_addr_and_sync);
4534 dst = cycles(dst, 18); 4570 dst = cycles(dst, 18);
4535 dst = jmp_r(dst, SCRATCH1); 4571 dst = jmp_r(dst, SCRATCH1);
4536 4572
4537 opts->cur_code = dst; 4573 opts->cur_code = dst;
4538 } 4574 }