comparison z80_to_x86.c @ 627:c5820734a5b6

Added some preliminary support for interpreting Z80 code from non-RAM addresses
author Michael Pavone <pavone@retrodev.com>
date Fri, 20 Jun 2014 07:57:32 -0700
parents 7c46891a29b1
children 041578693329
comparison
equal deleted inserted replaced
626:7c46891a29b1 627:c5820734a5b6
326 (context->alt_regs[Z80_IXH] << 8) | context->alt_regs[Z80_IXL], 326 (context->alt_regs[Z80_IXH] << 8) | context->alt_regs[Z80_IXL],
327 (context->alt_regs[Z80_IYH] << 8) | context->alt_regs[Z80_IYL]); 327 (context->alt_regs[Z80_IYH] << 8) | context->alt_regs[Z80_IYL]);
328 exit(0); 328 exit(0);
329 } 329 }
330 330
331 uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context, uint16_t address) 331 uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context, uint16_t address, uint8_t interp)
332 { 332 {
333 uint32_t cycles; 333 uint32_t cycles;
334 x86_ea src_op, dst_op; 334 x86_ea src_op, dst_op;
335 uint8_t size; 335 uint8_t size;
336 x86_z80_options *opts = context->options; 336 x86_z80_options *opts = context->options;
337 uint8_t * start = dst; 337 uint8_t * start = dst;
338 dst = z80_check_cycles_int(dst, address); 338 if (!interp) {
339 if (context->breakpoint_flags[address / sizeof(uint8_t)] & (1 << (address % sizeof(uint8_t)))) { 339 dst = z80_check_cycles_int(dst, address);
340 zbreakpoint_patch(context, address, start); 340 if (context->breakpoint_flags[address / sizeof(uint8_t)] & (1 << (address % sizeof(uint8_t)))) {
341 zbreakpoint_patch(context, address, start);
342 }
341 } 343 }
342 switch(inst->op) 344 switch(inst->op)
343 { 345 {
344 case Z80_LD: 346 case Z80_LD:
345 size = z80_size(inst); 347 size = z80_size(inst);
1658 } 1660 }
1659 } 1661 }
1660 return dst; 1662 return dst;
1661 } 1663 }
1662 1664
1665 uint8_t * z80_interp_handler(uint8_t opcode, z80_context * context)
1666 {
1667 if (!context->interp_code[opcode]) {
1668 if (opcode == 0xCB || (opcode >= 0xDD && opcode & 0xF == 0xD)) {
1669 fprintf(stderr, "Encountered prefix byte %X at address %X. Z80 interpeter doesn't support those yet.", opcode, context->pc);
1670 exit(1);
1671 }
1672 uint8_t codebuf[8];
1673 memset(codebuf, 0, sizeof(codebuf));
1674 codebuf[0] = opcode;
1675 z80inst inst;
1676 uint8_t * after = z80_decode(codebuf, &inst);
1677 if (after - codebuf > 1) {
1678 fprintf(stderr, "Encountered multi-byte Z80 instruction at %X. Z80 interpeter doesn't support those yet.", context->pc);
1679 exit(1);
1680 }
1681 x86_z80_options * opts = context->options;
1682 if (opts->code_end - opts->cur_code < ZMAX_NATIVE_SIZE) {
1683 size_t size = 1024*1024;
1684 opts->cur_code = alloc_code(&size);
1685 opts->code_end = opts->cur_code + size;
1686 }
1687 context->interp_code[opcode] = opts->cur_code;
1688 opts->cur_code = translate_z80inst(&inst, opts->cur_code, context, 0, 1);
1689 opts->cur_code = mov_rdisp8r(opts->cur_code, CONTEXT, offsetof(z80_context, pc), SCRATCH1, SZ_W);
1690 opts->cur_code = add_ir(opts->cur_code, after - codebuf, SCRATCH1, SZ_W);
1691 opts->cur_code = call(opts->cur_code, (uint8_t *)z80_native_addr);
1692 opts->cur_code = jmp_r(opts->cur_code, SCRATCH1);
1693 }
1694 return context->interp_code[opcode];
1695 }
1696
1697 uint8_t * z80_make_interp_stub(z80_context * context, uint16_t address)
1698 {
1699 x86_z80_options *opts = context->options;
1700 uint8_t *dst = opts->cur_code;
1701 //TODO: make this play well with the breakpoint code
1702 dst = mov_ir(dst, address, SCRATCH1, SZ_W);
1703 dst = call(dst, (uint8_t *)z80_read_byte);
1704 //normal opcode fetch is already factored into instruction timing
1705 //back out the base 3 cycles from a read here
1706 //not quite perfect, but it will have to do for now
1707 dst = sub_ir(dst, 3, ZCYCLES, SZ_D);
1708 dst = z80_check_cycles_int(dst, address);
1709 dst = call(dst, (uint8_t *)z80_save_context);
1710 dst = mov_rr(dst, SCRATCH1, RDI, SZ_B);
1711 dst = mov_irdisp8(dst, address, CONTEXT, offsetof(z80_context, pc), SZ_W);
1712 dst = push_r(dst, CONTEXT);
1713 dst = call(dst, (uint8_t *)z80_interp_handler);
1714 dst = mov_rr(dst, RAX, SCRATCH1, SZ_Q);
1715 dst = pop_r(dst, CONTEXT);
1716 dst = call(dst, (uint8_t *)z80_load_context);
1717 dst = jmp_r(dst, SCRATCH1);
1718 opts->code_end = dst;
1719 return dst;
1720 }
1721
1722
1663 uint8_t * z80_get_native_address(z80_context * context, uint32_t address) 1723 uint8_t * z80_get_native_address(z80_context * context, uint32_t address)
1664 { 1724 {
1665 native_map_slot *map; 1725 native_map_slot *map;
1666 if (address < 0x4000) { 1726 if (address < 0x4000) {
1667 address &= 0x1FFF; 1727 address &= 0x1FFF;
1668 map = context->static_code_map; 1728 map = context->static_code_map;
1669 } else if (address >= 0x8000) {
1670 address &= 0x7FFF;
1671 map = context->banked_code_map + context->bank_reg;
1672 } else { 1729 } else {
1673 //dprintf("z80_get_native_address: %X NULL\n", address); 1730 address -= 0x4000;
1674 return NULL; 1731 map = context->banked_code_map;
1675 } 1732 }
1676 if (!map->base || !map->offsets || map->offsets[address] == INVALID_OFFSET || map->offsets[address] == EXTENSION_WORD) { 1733 if (!map->base || !map->offsets || map->offsets[address] == INVALID_OFFSET || map->offsets[address] == EXTENSION_WORD) {
1677 //dprintf("z80_get_native_address: %X NULL\n", address); 1734 //dprintf("z80_get_native_address: %X NULL\n", address);
1678 return NULL; 1735 return NULL;
1679 } 1736 }
1681 return map->base + map->offsets[address]; 1738 return map->base + map->offsets[address];
1682 } 1739 }
1683 1740
1684 uint8_t z80_get_native_inst_size(x86_z80_options * opts, uint32_t address) 1741 uint8_t z80_get_native_inst_size(x86_z80_options * opts, uint32_t address)
1685 { 1742 {
1743 //TODO: Fix for addresses >= 0x4000
1686 if (address >= 0x4000) { 1744 if (address >= 0x4000) {
1687 return 0; 1745 return 0;
1688 } 1746 }
1689 return opts->ram_inst_sizes[address & 0x1FFF]; 1747 return opts->ram_inst_sizes[address & 0x1FFF];
1690 } 1748 }
1698 address &= 0x1FFF; 1756 address &= 0x1FFF;
1699 map = context->static_code_map; 1757 map = context->static_code_map;
1700 opts->ram_inst_sizes[address] = native_size; 1758 opts->ram_inst_sizes[address] = native_size;
1701 context->ram_code_flags[(address & 0x1C00) >> 10] |= 1 << ((address & 0x380) >> 7); 1759 context->ram_code_flags[(address & 0x1C00) >> 10] |= 1 << ((address & 0x380) >> 7);
1702 context->ram_code_flags[((address + size) & 0x1C00) >> 10] |= 1 << (((address + size) & 0x380) >> 7); 1760 context->ram_code_flags[((address + size) & 0x1C00) >> 10] |= 1 << (((address + size) & 0x380) >> 7);
1703 } else if (address >= 0x8000) { 1761 } else {
1704 address &= 0x7FFF; 1762 //HERE
1705 map = context->banked_code_map + context->bank_reg; 1763 address -= 0x4000;
1764 map = context->banked_code_map;
1706 if (!map->offsets) { 1765 if (!map->offsets) {
1707 map->offsets = malloc(sizeof(int32_t) * 0x8000); 1766 map->offsets = malloc(sizeof(int32_t) * 0xC000);
1708 memset(map->offsets, 0xFF, sizeof(int32_t) * 0x8000); 1767 memset(map->offsets, 0xFF, sizeof(int32_t) * 0xC000);
1709 } 1768 }
1710 } else {
1711 return;
1712 } 1769 }
1713 if (!map->base) { 1770 if (!map->base) {
1714 map->base = native_address; 1771 map->base = native_address;
1715 } 1772 }
1716 map->offsets[address] = native_address - map->base; 1773 map->offsets[address] = native_address - map->base;
1717 for(--size, orig_address++; size; --size, orig_address++) { 1774 for(--size, orig_address++; size; --size, orig_address++) {
1718 address = orig_address; 1775 address = orig_address;
1719 if (address < 0x4000) { 1776 if (address < 0x4000) {
1720 address &= 0x1FFF; 1777 address &= 0x1FFF;
1721 map = context->static_code_map; 1778 map = context->static_code_map;
1722 } else if (address >= 0x8000) { 1779 } else {
1723 address &= 0x7FFF; 1780 address -= 0x4000;
1724 map = context->banked_code_map + context->bank_reg; 1781 map = context->banked_code_map;
1725 } else {
1726 return;
1727 } 1782 }
1728 if (!map->offsets) { 1783 if (!map->offsets) {
1729 map->offsets = malloc(sizeof(int32_t) * 0x8000); 1784 map->offsets = malloc(sizeof(int32_t) * 0xC000);
1730 memset(map->offsets, 0xFF, sizeof(int32_t) * 0x8000); 1785 memset(map->offsets, 0xFF, sizeof(int32_t) * 0xC000);
1731 } 1786 }
1732 map->offsets[address] = EXTENSION_WORD; 1787 map->offsets[address] = EXTENSION_WORD;
1733 } 1788 }
1734 } 1789 }
1735 1790
1736 #define INVALID_INSTRUCTION_START 0xFEEDFEED 1791 #define INVALID_INSTRUCTION_START 0xFEEDFEED
1737 1792
1738 uint32_t z80_get_instruction_start(native_map_slot * static_code_map, uint32_t address) 1793 uint32_t z80_get_instruction_start(native_map_slot * static_code_map, uint32_t address)
1739 { 1794 {
1795 //TODO: Fixme for address >= 0x4000
1740 if (!static_code_map->base || address >= 0x4000) { 1796 if (!static_code_map->base || address >= 0x4000) {
1741 return INVALID_INSTRUCTION_START; 1797 return INVALID_INSTRUCTION_START;
1742 } 1798 }
1743 address &= 0x1FFF; 1799 address &= 0x1FFF;
1744 if (static_code_map->offsets[address] == INVALID_OFFSET) { 1800 if (static_code_map->offsets[address] == INVALID_OFFSET) {
1812 dst = alloc_code(&size); 1868 dst = alloc_code(&size);
1813 opts->code_end = dst_end = dst + size; 1869 opts->code_end = dst_end = dst + size;
1814 opts->cur_code = dst; 1870 opts->cur_code = dst;
1815 } 1871 }
1816 deferred_addr * orig_deferred = opts->deferred; 1872 deferred_addr * orig_deferred = opts->deferred;
1817 uint8_t * native_end = translate_z80inst(&instbuf, dst, context, address); 1873 uint8_t * native_end = translate_z80inst(&instbuf, dst, context, address, 0);
1818 if ((native_end - dst) <= orig_size) { 1874 if ((native_end - dst) <= orig_size) {
1819 uint8_t * native_next = z80_get_native_address(context, address + after-inst); 1875 uint8_t * native_next = z80_get_native_address(context, address + after-inst);
1820 if (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - dst)) > 5)) { 1876 if (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - dst)) > 5)) {
1821 remove_deferred_until(&opts->deferred, orig_deferred); 1877 remove_deferred_until(&opts->deferred, orig_deferred);
1822 native_end = translate_z80inst(&instbuf, orig_start, context, address); 1878 native_end = translate_z80inst(&instbuf, orig_start, context, address, 0);
1823 if (native_next == orig_start + orig_size && (native_next-native_end) < 2) { 1879 if (native_next == orig_start + orig_size && (native_next-native_end) < 2) {
1824 while (native_end < orig_start + orig_size) { 1880 while (native_end < orig_start + orig_size) {
1825 *(native_end++) = 0x90; //NOP 1881 *(native_end++) = 0x90; //NOP
1826 } 1882 }
1827 } else { 1883 } else {
1838 jmp(native_end, z80_get_native_address_trans(context, address + after-inst)); 1894 jmp(native_end, z80_get_native_address_trans(context, address + after-inst));
1839 } 1895 }
1840 z80_handle_deferred(context); 1896 z80_handle_deferred(context);
1841 return dst; 1897 return dst;
1842 } else { 1898 } else {
1843 dst = translate_z80inst(&instbuf, orig_start, context, address); 1899 dst = translate_z80inst(&instbuf, orig_start, context, address, 0);
1844 if (!z80_is_terminal(&instbuf)) { 1900 if (!z80_is_terminal(&instbuf)) {
1845 dst = jmp(dst, z80_get_native_address_trans(context, address + after-inst)); 1901 dst = jmp(dst, z80_get_native_address_trans(context, address + after-inst));
1846 } 1902 }
1847 z80_handle_deferred(context); 1903 z80_handle_deferred(context);
1848 return orig_start; 1904 return orig_start;
1858 x86_z80_options * opts = context->options; 1914 x86_z80_options * opts = context->options;
1859 uint32_t start_address = address; 1915 uint32_t start_address = address;
1860 uint8_t * encoded = NULL, *next; 1916 uint8_t * encoded = NULL, *next;
1861 if (address < 0x4000) { 1917 if (address < 0x4000) {
1862 encoded = context->mem_pointers[0] + (address & 0x1FFF); 1918 encoded = context->mem_pointers[0] + (address & 0x1FFF);
1863 } else if(address >= 0x8000 && context->mem_pointers[1]) { 1919 }
1864 printf("attempt to translate Z80 code from banked area at address %X\n", address); 1920
1865 exit(1); 1921 while (encoded != NULL || address >= 0x4000)
1866 //encoded = context->mem_pointers[1] + (address & 0x7FFF);
1867 }
1868 while (encoded != NULL)
1869 { 1922 {
1870 z80inst inst; 1923 z80inst inst;
1871 dprintf("translating Z80 code at address %X\n", address); 1924 dprintf("translating Z80 code at address %X\n", address);
1872 do { 1925 do {
1873 if (opts->code_end-opts->cur_code < ZMAX_NATIVE_SIZE) { 1926 if (opts->code_end-opts->cur_code < ZMAX_NATIVE_SIZE) {
1878 size_t size = 1024*1024; 1931 size_t size = 1024*1024;
1879 opts->cur_code = alloc_code(&size); 1932 opts->cur_code = alloc_code(&size);
1880 opts->code_end = opts->cur_code + size; 1933 opts->code_end = opts->cur_code + size;
1881 jmp(opts->cur_code, opts->cur_code); 1934 jmp(opts->cur_code, opts->cur_code);
1882 } 1935 }
1883 if (address > 0x4000 && address < 0x8000) { 1936 if (address >= 0x4000) {
1884 opts->cur_code = xor_rr(opts->cur_code, RDI, RDI, SZ_D); 1937 uint8_t *native_start = opts->cur_code;
1885 opts->cur_code = call(opts->cur_code, (uint8_t *)exit); 1938 uint8_t *after = z80_make_interp_stub(context, address);
1939 z80_map_native_address(context, address, opts->cur_code, 1, after - native_start);
1886 break; 1940 break;
1887 } 1941 }
1888 uint8_t * existing = z80_get_native_address(context, address); 1942 uint8_t * existing = z80_get_native_address(context, address);
1889 if (existing) { 1943 if (existing) {
1890 opts->cur_code = jmp(opts->cur_code, existing); 1944 opts->cur_code = jmp(opts->cur_code, existing);
1897 printf("%X\t%s(%d)\n", address, disbuf, inst.immed); 1951 printf("%X\t%s(%d)\n", address, disbuf, inst.immed);
1898 } else { 1952 } else {
1899 printf("%X\t%s\n", address, disbuf); 1953 printf("%X\t%s\n", address, disbuf);
1900 } 1954 }
1901 #endif 1955 #endif
1902 uint8_t *after = translate_z80inst(&inst, opts->cur_code, context, address); 1956 uint8_t *after = translate_z80inst(&inst, opts->cur_code, context, address, 0);
1903 z80_map_native_address(context, address, opts->cur_code, next-encoded, after - opts->cur_code); 1957 z80_map_native_address(context, address, opts->cur_code, next-encoded, after - opts->cur_code);
1904 opts->cur_code = after; 1958 opts->cur_code = after;
1905 address += next-encoded; 1959 address += next-encoded;
1906 if (address > 0xFFFF) { 1960 if (address > 0xFFFF) {
1907 address &= 0xFFFF; 1961 address &= 0xFFFF;
1914 if (opts->deferred) { 1968 if (opts->deferred) {
1915 address = opts->deferred->address; 1969 address = opts->deferred->address;
1916 dprintf("defferred address: %X\n", address); 1970 dprintf("defferred address: %X\n", address);
1917 if (address < 0x4000) { 1971 if (address < 0x4000) {
1918 encoded = context->mem_pointers[0] + (address & 0x1FFF); 1972 encoded = context->mem_pointers[0] + (address & 0x1FFF);
1919 } else if (address > 0x8000 && context->mem_pointers[1]) {
1920 encoded = context->mem_pointers[1] + (address & 0x7FFF);
1921 } else { 1973 } else {
1922 printf("attempt to translate non-memory address: %X\n", address); 1974 encoded = NULL;
1923 exit(1);
1924 } 1975 }
1925 } else { 1976 } else {
1926 encoded = NULL; 1977 encoded = NULL;
1978 address = 0;
1927 } 1979 }
1928 } 1980 }
1929 } 1981 }
1930 1982
1931 void init_x86_z80_opts(x86_z80_options * options) 1983 void init_x86_z80_opts(x86_z80_options * options)
1964 memset(context, 0, sizeof(*context)); 2016 memset(context, 0, sizeof(*context));
1965 context->static_code_map = malloc(sizeof(*context->static_code_map)); 2017 context->static_code_map = malloc(sizeof(*context->static_code_map));
1966 context->static_code_map->base = NULL; 2018 context->static_code_map->base = NULL;
1967 context->static_code_map->offsets = malloc(sizeof(int32_t) * 0x2000); 2019 context->static_code_map->offsets = malloc(sizeof(int32_t) * 0x2000);
1968 memset(context->static_code_map->offsets, 0xFF, sizeof(int32_t) * 0x2000); 2020 memset(context->static_code_map->offsets, 0xFF, sizeof(int32_t) * 0x2000);
1969 context->banked_code_map = malloc(sizeof(native_map_slot) * (1 << 9)); 2021 context->banked_code_map = malloc(sizeof(native_map_slot));
1970 memset(context->banked_code_map, 0, sizeof(native_map_slot) * (1 << 9)); 2022 memset(context->banked_code_map, 0, sizeof(native_map_slot));
1971 context->options = options; 2023 context->options = options;
1972 context->int_cycle = 0xFFFFFFFF; 2024 context->int_cycle = 0xFFFFFFFF;
1973 } 2025 }
1974 2026
1975 void z80_reset(z80_context * context) 2027 void z80_reset(z80_context * context)