Mercurial > repos > blastem
comparison z80_to_x86.c @ 682:7ed1dbb48f61
Merge
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 04 Jan 2015 23:35:55 -0800 |
parents | 41a399c11ef1 6b248602ab84 |
children | 7f96bd1cb1be |
comparison
equal
deleted
inserted
replaced
681:e26640daf1ae | 682:7ed1dbb48f61 |
---|---|
1375 uint8_t *no_jump_off = code->cur+1; | 1375 uint8_t *no_jump_off = code->cur+1; |
1376 jcc(code, cond, code->cur+2); | 1376 jcc(code, cond, code->cur+2); |
1377 cycles(&opts->gen, 5);//T States: 5 | 1377 cycles(&opts->gen, 5);//T States: 5 |
1378 uint16_t dest_addr = inst->immed; | 1378 uint16_t dest_addr = inst->immed; |
1379 code_ptr call_dst = z80_get_native_address(context, dest_addr); | 1379 code_ptr call_dst = z80_get_native_address(context, dest_addr); |
1380 if (!call_dst) { | 1380 if (!call_dst) { |
1381 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); | 1381 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); |
1382 //fake address to force large displacement | 1382 //fake address to force large displacement |
1383 call_dst = code->cur + 256; | 1383 call_dst = code->cur + 256; |
1384 } | 1384 } |
1385 jmp(code, call_dst); | 1385 jmp(code, call_dst); |
1386 *no_jump_off = code->cur - (no_jump_off+1); | 1386 *no_jump_off = code->cur - (no_jump_off+1); |
1387 break; | 1387 break; |
1388 } | 1388 } |
1389 case Z80_JR: { | 1389 case Z80_JR: { |
1390 cycles(&opts->gen, 12);//T States: 4,3,5 | 1390 cycles(&opts->gen, 12);//T States: 4,3,5 |
1391 uint16_t dest_addr = address + inst->immed + 2; | 1391 uint16_t dest_addr = address + inst->immed + 2; |
1392 code_ptr call_dst = z80_get_native_address(context, dest_addr); | 1392 code_ptr call_dst = z80_get_native_address(context, dest_addr); |
1393 if (!call_dst) { | 1393 if (!call_dst) { |
1394 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); | 1394 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); |
1395 //fake address to force large displacement | 1395 //fake address to force large displacement |
1396 call_dst = code->cur + 256; | 1396 call_dst = code->cur + 256; |
1397 } | 1397 } |
1398 jmp(code, call_dst); | 1398 jmp(code, call_dst); |
1399 break; | 1399 break; |
1400 } | 1400 } |
1401 case Z80_JRCC: { | 1401 case Z80_JRCC: { |
1402 cycles(&opts->gen, 7);//T States: 4,3 | 1402 cycles(&opts->gen, 7);//T States: 4,3 |
1417 uint8_t *no_jump_off = code->cur+1; | 1417 uint8_t *no_jump_off = code->cur+1; |
1418 jcc(code, cond, code->cur+2); | 1418 jcc(code, cond, code->cur+2); |
1419 cycles(&opts->gen, 5);//T States: 5 | 1419 cycles(&opts->gen, 5);//T States: 5 |
1420 uint16_t dest_addr = address + inst->immed + 2; | 1420 uint16_t dest_addr = address + inst->immed + 2; |
1421 code_ptr call_dst = z80_get_native_address(context, dest_addr); | 1421 code_ptr call_dst = z80_get_native_address(context, dest_addr); |
1422 if (!call_dst) { | 1422 if (!call_dst) { |
1423 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); | 1423 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); |
1424 //fake address to force large displacement | 1424 //fake address to force large displacement |
1425 call_dst = code->cur + 256; | 1425 call_dst = code->cur + 256; |
1426 } | 1426 } |
1427 jmp(code, call_dst); | 1427 jmp(code, call_dst); |
1428 *no_jump_off = code->cur - (no_jump_off+1); | 1428 *no_jump_off = code->cur - (no_jump_off+1); |
1429 break; | 1429 break; |
1430 } | 1430 } |
1431 case Z80_DJNZ: { | 1431 case Z80_DJNZ: { |
1434 uint8_t *no_jump_off = code->cur+1; | 1434 uint8_t *no_jump_off = code->cur+1; |
1435 jcc(code, CC_Z, code->cur+2); | 1435 jcc(code, CC_Z, code->cur+2); |
1436 cycles(&opts->gen, 5);//T States: 5 | 1436 cycles(&opts->gen, 5);//T States: 5 |
1437 uint16_t dest_addr = address + inst->immed + 2; | 1437 uint16_t dest_addr = address + inst->immed + 2; |
1438 code_ptr call_dst = z80_get_native_address(context, dest_addr); | 1438 code_ptr call_dst = z80_get_native_address(context, dest_addr); |
1439 if (!call_dst) { | 1439 if (!call_dst) { |
1440 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); | 1440 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); |
1441 //fake address to force large displacement | 1441 //fake address to force large displacement |
1442 call_dst = code->cur + 256; | 1442 call_dst = code->cur + 256; |
1443 } | 1443 } |
1444 jmp(code, call_dst); | 1444 jmp(code, call_dst); |
1445 *no_jump_off = code->cur - (no_jump_off+1); | 1445 *no_jump_off = code->cur - (no_jump_off+1); |
1446 break; | 1446 break; |
1447 } | 1447 } |
1448 case Z80_CALL: { | 1448 case Z80_CALL: { |
1449 cycles(&opts->gen, 11);//T States: 4,3,4 | 1449 cycles(&opts->gen, 11);//T States: 4,3,4 |
1450 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); | 1450 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); |
1451 mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); | 1451 mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); |
1452 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); | 1452 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); |
1453 call(code, opts->write_16_highfirst);//T States: 3, 3 | 1453 call(code, opts->write_16_highfirst);//T States: 3, 3 |
1454 code_ptr call_dst = z80_get_native_address(context, inst->immed); | 1454 code_ptr call_dst = z80_get_native_address(context, inst->immed); |
1455 if (!call_dst) { | 1455 if (!call_dst) { |
1456 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); | 1456 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); |
1457 //fake address to force large displacement | 1457 //fake address to force large displacement |
1458 call_dst = code->cur + 256; | 1458 call_dst = code->cur + 256; |
1459 } | 1459 } |
1460 jmp(code, call_dst); | 1460 jmp(code, call_dst); |
1461 break; | 1461 break; |
1462 } | 1462 } |
1463 case Z80_CALLCC: { | 1463 case Z80_CALLCC: { |
1464 cycles(&opts->gen, 10);//T States: 4,3,3 (false case) | 1464 cycles(&opts->gen, 10);//T States: 4,3,3 (false case) |
1492 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); | 1492 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); |
1493 mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); | 1493 mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); |
1494 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); | 1494 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); |
1495 call(code, opts->write_16_highfirst);//T States: 3, 3 | 1495 call(code, opts->write_16_highfirst);//T States: 3, 3 |
1496 code_ptr call_dst = z80_get_native_address(context, inst->immed); | 1496 code_ptr call_dst = z80_get_native_address(context, inst->immed); |
1497 if (!call_dst) { | 1497 if (!call_dst) { |
1498 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); | 1498 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); |
1499 //fake address to force large displacement | 1499 //fake address to force large displacement |
1500 call_dst = code->cur + 256; | 1500 call_dst = code->cur + 256; |
1501 } | 1501 } |
1502 jmp(code, call_dst); | 1502 jmp(code, call_dst); |
1503 *no_call_off = code->cur - (no_call_off+1); | 1503 *no_call_off = code->cur - (no_call_off+1); |
1504 break; | 1504 break; |
1505 } | 1505 } |
1506 case Z80_RET: | 1506 case Z80_RET: |
1507 cycles(&opts->gen, 4);//T States: 4 | 1507 cycles(&opts->gen, 4);//T States: 4 |
1508 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); | 1508 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); |
1509 call(code, opts->read_16);//T STates: 3, 3 | 1509 call(code, opts->read_16);//T STates: 3, 3 |
1510 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); | 1510 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); |
1804 if (opts->gen.deferred) { | 1804 if (opts->gen.deferred) { |
1805 translate_z80_stream(context, opts->gen.deferred->address); | 1805 translate_z80_stream(context, opts->gen.deferred->address); |
1806 } | 1806 } |
1807 } | 1807 } |
1808 | 1808 |
1809 extern void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * orig_start) asm("z80_retranslate_inst"); | |
1809 void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * orig_start) | 1810 void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * orig_start) |
1810 { | 1811 { |
1811 char disbuf[80]; | 1812 char disbuf[80]; |
1812 z80_options * opts = context->options; | 1813 z80_options * opts = context->options; |
1813 uint8_t orig_size = z80_get_native_inst_size(opts, address); | 1814 uint8_t orig_size = z80_get_native_inst_size(opts, address); |
1911 #endif | 1912 #endif |
1912 code_ptr start = opts->gen.code.cur; | 1913 code_ptr start = opts->gen.code.cur; |
1913 translate_z80inst(&inst, context, address, 0); | 1914 translate_z80inst(&inst, context, address, 0); |
1914 z80_map_native_address(context, address, start, next-encoded, opts->gen.code.cur - start); | 1915 z80_map_native_address(context, address, start, next-encoded, opts->gen.code.cur - start); |
1915 address += next-encoded; | 1916 address += next-encoded; |
1916 address &= 0xFFFF; | 1917 address &= 0xFFFF; |
1917 } while (!z80_is_terminal(&inst)); | 1918 } while (!z80_is_terminal(&inst)); |
1918 process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address); | 1919 process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address); |
1919 if (opts->gen.deferred) { | 1920 if (opts->gen.deferred) { |
1920 address = opts->gen.deferred->address; | 1921 address = opts->gen.deferred->address; |
1921 dprintf("defferred address: %X\n", address); | 1922 dprintf("defferred address: %X\n", address); |
1922 } | 1923 } |
1923 } while (opts->gen.deferred); | 1924 } while (opts->gen.deferred); |
1924 } | 1925 } |
1925 | 1926 |
1926 void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks, uint32_t clock_divider) | 1927 void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks, uint32_t clock_divider) |
1927 { | 1928 { |
2275 void z80_clear_reset(z80_context * context, uint32_t cycle) | 2276 void z80_clear_reset(z80_context * context, uint32_t cycle) |
2276 { | 2277 { |
2277 z80_run(context, cycle); | 2278 z80_run(context, cycle); |
2278 if (context->reset) { | 2279 if (context->reset) { |
2279 //TODO: Handle case where reset is not asserted long enough | 2280 //TODO: Handle case where reset is not asserted long enough |
2280 context->im = 0; | 2281 context->im = 0; |
2281 context->iff1 = context->iff2 = 0; | 2282 context->iff1 = context->iff2 = 0; |
2282 context->native_pc = NULL; | 2283 context->native_pc = NULL; |
2283 context->extra_pc = NULL; | 2284 context->extra_pc = NULL; |
2284 context->pc = 0; | 2285 context->pc = 0; |
2285 context->reset = 0; | 2286 context->reset = 0; |
2286 if (context->busreq) { | 2287 if (context->busreq) { |
2287 //TODO: Figure out appropriate delay | 2288 //TODO: Figure out appropriate delay |
2288 context->busack = 1; | 2289 context->busack = 1; |
2292 | 2293 |
2293 void z80_assert_busreq(z80_context * context, uint32_t cycle) | 2294 void z80_assert_busreq(z80_context * context, uint32_t cycle) |
2294 { | 2295 { |
2295 z80_run(context, cycle); | 2296 z80_run(context, cycle); |
2296 context->busreq = 1; | 2297 context->busreq = 1; |
2297 } | 2298 } |
2298 | 2299 |
2299 void z80_clear_busreq(z80_context * context, uint32_t cycle) | 2300 void z80_clear_busreq(z80_context * context, uint32_t cycle) |
2300 { | 2301 { |
2301 z80_run(context, cycle); | 2302 z80_run(context, cycle); |
2302 context->busreq = 0; | 2303 context->busreq = 0; |
2351 z80_options * opts = context->options; | 2352 z80_options * opts = context->options; |
2352 code_info *code = &opts->gen.code; | 2353 code_info *code = &opts->gen.code; |
2353 check_code_prologue(code); | 2354 check_code_prologue(code); |
2354 context->bp_stub = code->cur; | 2355 context->bp_stub = code->cur; |
2355 | 2356 |
2356 //Calculate length of prologue | 2357 //Calculate length of prologue |
2357 check_cycles_int(&opts->gen, 0); | 2358 check_cycles_int(&opts->gen, 0); |
2358 int check_int_size = code->cur-context->bp_stub; | 2359 int check_int_size = code->cur-context->bp_stub; |
2359 code->cur = context->bp_stub; | 2360 code->cur = context->bp_stub; |
2360 | 2361 |
2361 //Calculate length of patch | 2362 //Calculate length of patch |
2362 int patch_size = zbreakpoint_patch(context, 0, code->cur); | 2363 int patch_size = zbreakpoint_patch(context, 0, code->cur); |
2363 | 2364 |
2364 //Save context and call breakpoint handler | 2365 //Save context and call breakpoint handler |
2365 call(code, opts->gen.save_context); | 2366 call(code, opts->gen.save_context); |
2366 push_r(code, opts->gen.scratch1); | 2367 push_r(code, opts->gen.scratch1); |
2367 call_args_abi(code, context->bp_handler, 2, opts->gen.context_reg, opts->gen.scratch1); | 2368 call_args_abi(code, context->bp_handler, 2, opts->gen.context_reg, opts->gen.scratch1); |
2368 mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR); | 2369 mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR); |
2369 //Restore context | 2370 //Restore context |
2370 call(code, opts->gen.load_context); | 2371 call(code, opts->gen.load_context); |
2371 pop_r(code, opts->gen.scratch1); | 2372 pop_r(code, opts->gen.scratch1); |
2372 //do prologue stuff | 2373 //do prologue stuff |
2373 cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D); | 2374 cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D); |
2374 uint8_t * jmp_off = code->cur+1; | 2375 uint8_t * jmp_off = code->cur+1; |
2375 jcc(code, CC_NC, code->cur + 7); | 2376 jcc(code, CC_NC, code->cur + 7); |
2376 pop_r(code, opts->gen.scratch1); | 2377 pop_r(code, opts->gen.scratch1); |
2377 add_ir(code, check_int_size - patch_size, opts->gen.scratch1, SZ_PTR); | 2378 add_ir(code, check_int_size - patch_size, opts->gen.scratch1, SZ_PTR); |
2378 push_r(code, opts->gen.scratch1); | 2379 push_r(code, opts->gen.scratch1); |
2379 jmp(code, opts->gen.handle_cycle_limit_int); | 2380 jmp(code, opts->gen.handle_cycle_limit_int); |
2380 *jmp_off = code->cur - (jmp_off+1); | 2381 *jmp_off = code->cur - (jmp_off+1); |
2381 //jump back to body of translated instruction | 2382 //jump back to body of translated instruction |
2382 pop_r(code, opts->gen.scratch1); | 2383 pop_r(code, opts->gen.scratch1); |
2383 add_ir(code, check_int_size - patch_size, opts->gen.scratch1, SZ_PTR); | 2384 add_ir(code, check_int_size - patch_size, opts->gen.scratch1, SZ_PTR); |
2384 jmp_r(code, opts->gen.scratch1); | 2385 jmp_r(code, opts->gen.scratch1); |
2385 } | 2386 } |
2386 | 2387 |
2409 code_info tmp_code = opts->gen.code; | 2410 code_info tmp_code = opts->gen.code; |
2410 opts->gen.code.cur = native; | 2411 opts->gen.code.cur = native; |
2411 opts->gen.code.last = native + 16; | 2412 opts->gen.code.last = native + 16; |
2412 check_cycles_int(&opts->gen, address); | 2413 check_cycles_int(&opts->gen, address); |
2413 opts->gen.code = tmp_code; | 2414 opts->gen.code = tmp_code; |
2414 } | 2415 } |
2415 } | 2416 } |
2416 | 2417 |