Mercurial > repos > blastem
comparison z80_to_x86.c @ 653:a18e3923481e
Remove some of the hard coded assumptions about the memory map from the CPU cores
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 01 Jan 2015 14:36:55 -0800 |
parents | f822d9216968 |
children | 92ce5ea5ffc9 |
comparison
equal
deleted
inserted
replaced
652:f822d9216968 | 653:a18e3923481e |
---|---|
1329 num_cycles += 6; | 1329 num_cycles += 6; |
1330 } else if(inst->ea_reg == Z80_IX || inst->ea_reg == Z80_IY) { | 1330 } else if(inst->ea_reg == Z80_IX || inst->ea_reg == Z80_IY) { |
1331 num_cycles += 4; | 1331 num_cycles += 4; |
1332 } | 1332 } |
1333 cycles(&opts->gen, num_cycles); | 1333 cycles(&opts->gen, num_cycles); |
1334 if (inst->addr_mode != Z80_REG_INDIRECT && inst->immed < 0x4000) { | 1334 if (inst->addr_mode != Z80_REG_INDIRECT) { |
1335 code_ptr call_dst = z80_get_native_address(context, inst->immed); | 1335 code_ptr call_dst = z80_get_native_address(context, inst->immed); |
1336 if (!call_dst) { | 1336 if (!call_dst) { |
1337 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); | 1337 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); |
1338 //fake address to force large displacement | 1338 //fake address to force large displacement |
1339 call_dst = code->cur + 256; | 1339 call_dst = code->cur + 256; |
1378 } | 1378 } |
1379 uint8_t *no_jump_off = code->cur+1; | 1379 uint8_t *no_jump_off = code->cur+1; |
1380 jcc(code, cond, code->cur+2); | 1380 jcc(code, cond, code->cur+2); |
1381 cycles(&opts->gen, 5);//T States: 5 | 1381 cycles(&opts->gen, 5);//T States: 5 |
1382 uint16_t dest_addr = inst->immed; | 1382 uint16_t dest_addr = inst->immed; |
1383 if (dest_addr < 0x4000) { | 1383 code_ptr call_dst = z80_get_native_address(context, dest_addr); |
1384 code_ptr call_dst = z80_get_native_address(context, dest_addr); | 1384 if (!call_dst) { |
1385 if (!call_dst) { | 1385 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); |
1386 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); | 1386 //fake address to force large displacement |
1387 //fake address to force large displacement | 1387 call_dst = code->cur + 256; |
1388 call_dst = code->cur + 256; | 1388 } |
1389 } | 1389 jmp(code, call_dst); |
1390 jmp(code, call_dst); | |
1391 } else { | |
1392 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); | |
1393 call(code, opts->native_addr); | |
1394 jmp_r(code, opts->gen.scratch1); | |
1395 } | |
1396 *no_jump_off = code->cur - (no_jump_off+1); | 1390 *no_jump_off = code->cur - (no_jump_off+1); |
1397 break; | 1391 break; |
1398 } | 1392 } |
1399 case Z80_JR: { | 1393 case Z80_JR: { |
1400 cycles(&opts->gen, 12);//T States: 4,3,5 | 1394 cycles(&opts->gen, 12);//T States: 4,3,5 |
1401 uint16_t dest_addr = address + inst->immed + 2; | 1395 uint16_t dest_addr = address + inst->immed + 2; |
1402 if (dest_addr < 0x4000) { | 1396 code_ptr call_dst = z80_get_native_address(context, dest_addr); |
1403 code_ptr call_dst = z80_get_native_address(context, dest_addr); | 1397 if (!call_dst) { |
1404 if (!call_dst) { | 1398 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); |
1405 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); | 1399 //fake address to force large displacement |
1406 //fake address to force large displacement | 1400 call_dst = code->cur + 256; |
1407 call_dst = code->cur + 256; | 1401 } |
1408 } | 1402 jmp(code, call_dst); |
1409 jmp(code, call_dst); | |
1410 } else { | |
1411 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); | |
1412 call(code, opts->native_addr); | |
1413 jmp_r(code, opts->gen.scratch1); | |
1414 } | |
1415 break; | 1403 break; |
1416 } | 1404 } |
1417 case Z80_JRCC: { | 1405 case Z80_JRCC: { |
1418 cycles(&opts->gen, 7);//T States: 4,3 | 1406 cycles(&opts->gen, 7);//T States: 4,3 |
1419 uint8_t cond = CC_Z; | 1407 uint8_t cond = CC_Z; |
1432 } | 1420 } |
1433 uint8_t *no_jump_off = code->cur+1; | 1421 uint8_t *no_jump_off = code->cur+1; |
1434 jcc(code, cond, code->cur+2); | 1422 jcc(code, cond, code->cur+2); |
1435 cycles(&opts->gen, 5);//T States: 5 | 1423 cycles(&opts->gen, 5);//T States: 5 |
1436 uint16_t dest_addr = address + inst->immed + 2; | 1424 uint16_t dest_addr = address + inst->immed + 2; |
1437 if (dest_addr < 0x4000) { | 1425 code_ptr call_dst = z80_get_native_address(context, dest_addr); |
1438 code_ptr call_dst = z80_get_native_address(context, dest_addr); | 1426 if (!call_dst) { |
1439 if (!call_dst) { | 1427 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); | 1428 //fake address to force large displacement |
1441 //fake address to force large displacement | 1429 call_dst = code->cur + 256; |
1442 call_dst = code->cur + 256; | 1430 } |
1443 } | 1431 jmp(code, call_dst); |
1444 jmp(code, call_dst); | |
1445 } else { | |
1446 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); | |
1447 call(code, opts->native_addr); | |
1448 jmp_r(code, opts->gen.scratch1); | |
1449 } | |
1450 *no_jump_off = code->cur - (no_jump_off+1); | 1432 *no_jump_off = code->cur - (no_jump_off+1); |
1451 break; | 1433 break; |
1452 } | 1434 } |
1453 case Z80_DJNZ: | 1435 case Z80_DJNZ: { |
1454 cycles(&opts->gen, 8);//T States: 5,3 | 1436 cycles(&opts->gen, 8);//T States: 5,3 |
1455 sub_ir(code, 1, opts->regs[Z80_B], SZ_B); | 1437 sub_ir(code, 1, opts->regs[Z80_B], SZ_B); |
1456 uint8_t *no_jump_off = code->cur+1; | 1438 uint8_t *no_jump_off = code->cur+1; |
1457 jcc(code, CC_Z, code->cur+2); | 1439 jcc(code, CC_Z, code->cur+2); |
1458 cycles(&opts->gen, 5);//T States: 5 | 1440 cycles(&opts->gen, 5);//T States: 5 |
1459 uint16_t dest_addr = address + inst->immed + 2; | 1441 uint16_t dest_addr = address + inst->immed + 2; |
1460 if (dest_addr < 0x4000) { | 1442 code_ptr call_dst = z80_get_native_address(context, dest_addr); |
1461 code_ptr call_dst = z80_get_native_address(context, dest_addr); | 1443 if (!call_dst) { |
1462 if (!call_dst) { | 1444 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); |
1463 opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); | 1445 //fake address to force large displacement |
1464 //fake address to force large displacement | 1446 call_dst = code->cur + 256; |
1465 call_dst = code->cur + 256; | 1447 } |
1466 } | 1448 jmp(code, call_dst); |
1467 jmp(code, call_dst); | |
1468 } else { | |
1469 mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); | |
1470 call(code, opts->native_addr); | |
1471 jmp_r(code, opts->gen.scratch1); | |
1472 } | |
1473 *no_jump_off = code->cur - (no_jump_off+1); | 1449 *no_jump_off = code->cur - (no_jump_off+1); |
1474 break; | 1450 break; |
1451 } | |
1475 case Z80_CALL: { | 1452 case Z80_CALL: { |
1476 cycles(&opts->gen, 11);//T States: 4,3,4 | 1453 cycles(&opts->gen, 11);//T States: 4,3,4 |
1477 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); | 1454 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); |
1478 mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); | 1455 mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); |
1479 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); | 1456 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); |
1480 call(code, opts->write_16_highfirst);//T States: 3, 3 | 1457 call(code, opts->write_16_highfirst);//T States: 3, 3 |
1481 if (inst->immed < 0x4000) { | 1458 code_ptr call_dst = z80_get_native_address(context, inst->immed); |
1482 code_ptr call_dst = z80_get_native_address(context, inst->immed); | 1459 if (!call_dst) { |
1483 if (!call_dst) { | 1460 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); |
1484 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); | 1461 //fake address to force large displacement |
1485 //fake address to force large displacement | 1462 call_dst = code->cur + 256; |
1486 call_dst = code->cur + 256; | 1463 } |
1487 } | 1464 jmp(code, call_dst); |
1488 jmp(code, call_dst); | 1465 break; |
1489 } else { | 1466 } |
1490 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W); | 1467 case Z80_CALLCC: { |
1491 call(code, opts->native_addr); | |
1492 jmp_r(code, opts->gen.scratch1); | |
1493 } | |
1494 break; | |
1495 } | |
1496 case Z80_CALLCC: | |
1497 cycles(&opts->gen, 10);//T States: 4,3,3 (false case) | 1468 cycles(&opts->gen, 10);//T States: 4,3,3 (false case) |
1498 uint8_t cond = CC_Z; | 1469 uint8_t cond = CC_Z; |
1499 switch (inst->reg) | 1470 switch (inst->reg) |
1500 { | 1471 { |
1501 case Z80_CC_NZ: | 1472 case Z80_CC_NZ: |
1524 cycles(&opts->gen, 1);//Last of the above T states takes an extra cycle in the true case | 1495 cycles(&opts->gen, 1);//Last of the above T states takes an extra cycle in the true case |
1525 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); | 1496 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); |
1526 mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); | 1497 mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); |
1527 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); | 1498 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); |
1528 call(code, opts->write_16_highfirst);//T States: 3, 3 | 1499 call(code, opts->write_16_highfirst);//T States: 3, 3 |
1529 if (inst->immed < 0x4000) { | 1500 code_ptr call_dst = z80_get_native_address(context, inst->immed); |
1530 code_ptr call_dst = z80_get_native_address(context, inst->immed); | 1501 if (!call_dst) { |
1531 if (!call_dst) { | 1502 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); |
1532 opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); | 1503 //fake address to force large displacement |
1533 //fake address to force large displacement | 1504 call_dst = code->cur + 256; |
1534 call_dst = code->cur + 256; | 1505 } |
1535 } | 1506 jmp(code, call_dst); |
1536 jmp(code, call_dst); | |
1537 } else { | |
1538 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W); | |
1539 call(code, opts->native_addr); | |
1540 jmp_r(code, opts->gen.scratch1); | |
1541 } | |
1542 *no_call_off = code->cur - (no_call_off+1); | 1507 *no_call_off = code->cur - (no_call_off+1); |
1543 break; | 1508 break; |
1509 } | |
1544 case Z80_RET: | 1510 case Z80_RET: |
1545 cycles(&opts->gen, 4);//T States: 4 | 1511 cycles(&opts->gen, 4);//T States: 4 |
1546 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); | 1512 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); |
1547 call(code, opts->read_16);//T STates: 3, 3 | 1513 call(code, opts->read_16);//T STates: 3, 3 |
1548 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); | 1514 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); |
1848 void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * orig_start) | 1814 void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * orig_start) |
1849 { | 1815 { |
1850 char disbuf[80]; | 1816 char disbuf[80]; |
1851 z80_options * opts = context->options; | 1817 z80_options * opts = context->options; |
1852 uint8_t orig_size = z80_get_native_inst_size(opts, address); | 1818 uint8_t orig_size = z80_get_native_inst_size(opts, address); |
1853 uint32_t orig = address; | |
1854 address &= 0x1FFF; | |
1855 code_info *code = &opts->gen.code; | 1819 code_info *code = &opts->gen.code; |
1856 uint8_t *after, *inst = context->mem_pointers[0] + address; | 1820 uint8_t *after, *inst = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen); |
1857 z80inst instbuf; | 1821 z80inst instbuf; |
1858 dprintf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start); | 1822 dprintf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start); |
1859 after = z80_decode(inst, &instbuf); | 1823 after = z80_decode(inst, &instbuf); |
1860 #ifdef DO_DEBUG_PRINT | 1824 #ifdef DO_DEBUG_PRINT |
1861 z80_disasm(&instbuf, disbuf, address); | 1825 z80_disasm(&instbuf, disbuf, address); |
1919 if (z80_get_native_address(context, address)) { | 1883 if (z80_get_native_address(context, address)) { |
1920 return; | 1884 return; |
1921 } | 1885 } |
1922 z80_options * opts = context->options; | 1886 z80_options * opts = context->options; |
1923 uint32_t start_address = address; | 1887 uint32_t start_address = address; |
1924 uint8_t * encoded = NULL, *next; | 1888 |
1925 if (address < 0x4000) { | 1889 do |
1926 encoded = context->mem_pointers[0] + (address & 0x1FFF); | |
1927 } | |
1928 | |
1929 while (encoded != NULL || address >= 0x4000) | |
1930 { | 1890 { |
1931 z80inst inst; | 1891 z80inst inst; |
1932 dprintf("translating Z80 code at address %X\n", address); | 1892 dprintf("translating Z80 code at address %X\n", address); |
1933 do { | 1893 do { |
1934 if (address >= 0x4000) { | |
1935 code_info stub = z80_make_interp_stub(context, address); | |
1936 z80_map_native_address(context, address, stub.cur, 1, stub.last - stub.cur); | |
1937 break; | |
1938 } | |
1939 uint8_t * existing = z80_get_native_address(context, address); | 1894 uint8_t * existing = z80_get_native_address(context, address); |
1940 if (existing) { | 1895 if (existing) { |
1941 jmp(&opts->gen.code, existing); | 1896 jmp(&opts->gen.code, existing); |
1897 break; | |
1898 } | |
1899 uint8_t * encoded, *next; | |
1900 encoded = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen); | |
1901 if (!encoded) { | |
1902 code_info stub = z80_make_interp_stub(context, address); | |
1903 z80_map_native_address(context, address, stub.cur, 1, stub.last - stub.cur); | |
1942 break; | 1904 break; |
1943 } | 1905 } |
1944 //make sure prologue is in a contiguous chunk of code | 1906 //make sure prologue is in a contiguous chunk of code |
1945 check_code_prologue(&opts->gen.code); | 1907 check_code_prologue(&opts->gen.code); |
1946 next = z80_decode(encoded, &inst); | 1908 next = z80_decode(encoded, &inst); |
1954 #endif | 1916 #endif |
1955 code_ptr start = opts->gen.code.cur; | 1917 code_ptr start = opts->gen.code.cur; |
1956 translate_z80inst(&inst, context, address, 0); | 1918 translate_z80inst(&inst, context, address, 0); |
1957 z80_map_native_address(context, address, start, next-encoded, opts->gen.code.cur - start); | 1919 z80_map_native_address(context, address, start, next-encoded, opts->gen.code.cur - start); |
1958 address += next-encoded; | 1920 address += next-encoded; |
1959 if (address > 0xFFFF) { | 1921 address &= 0xFFFF; |
1960 address &= 0xFFFF; | |
1961 | |
1962 } else { | |
1963 encoded = next; | |
1964 } | |
1965 } while (!z80_is_terminal(&inst)); | 1922 } while (!z80_is_terminal(&inst)); |
1966 process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address); | 1923 process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address); |
1967 if (opts->gen.deferred) { | 1924 if (opts->gen.deferred) { |
1968 address = opts->gen.deferred->address; | 1925 address = opts->gen.deferred->address; |
1969 dprintf("defferred address: %X\n", address); | 1926 dprintf("defferred address: %X\n", address); |
1970 if (address < 0x4000) { | 1927 } |
1971 encoded = context->mem_pointers[0] + (address & 0x1FFF); | 1928 } while (opts->gen.deferred); |
1972 } else { | |
1973 encoded = NULL; | |
1974 } | |
1975 } else { | |
1976 encoded = NULL; | |
1977 address = 0; | |
1978 } | |
1979 } | |
1980 } | 1929 } |
1981 | 1930 |
1982 void init_x86_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks) | 1931 void init_x86_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks) |
1983 { | 1932 { |
1984 memset(options, 0, sizeof(*options)); | 1933 memset(options, 0, sizeof(*options)); |
1985 | 1934 |
1935 options->gen.memmap = chunks; | |
1936 options->gen.memmap_chunks = num_chunks; | |
1986 options->gen.address_size = SZ_W; | 1937 options->gen.address_size = SZ_W; |
1987 options->gen.address_mask = 0xFFFF; | 1938 options->gen.address_mask = 0xFFFF; |
1988 options->gen.max_address = 0x10000; | 1939 options->gen.max_address = 0x10000; |
1989 options->gen.bus_cycles = 3; | 1940 options->gen.bus_cycles = 3; |
1990 options->gen.mem_ptr_off = offsetof(z80_context, mem_pointers); | 1941 options->gen.mem_ptr_off = offsetof(z80_context, mem_pointers); |