Mercurial > repos > blastem
comparison z80_to_x86.c @ 1040:fbfb821e92a8
Implement Z80 block OUT instructions. Fixes Power Monger
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 23 Jul 2016 12:43:52 -0700 |
parents | 1eb616b8cbe9 |
children | a6c6b621d0dc |
comparison
equal
deleted
inserted
replaced
1039:86ed81bb574f | 1040:fbfb821e92a8 |
---|---|
1931 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B); | 1931 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B); |
1932 } | 1932 } |
1933 call(code, opts->write_io); | 1933 call(code, opts->write_io); |
1934 z80_save_reg(inst, opts); | 1934 z80_save_reg(inst, opts); |
1935 break; | 1935 break; |
1936 /*case Z80_OUTI: | 1936 case Z80_OUTI: |
1937 case Z80_OTIR: | 1937 cycles(&opts->gen, 9);//T States: 4, 5 |
1938 //read from (HL) | |
1939 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); | |
1940 call(code, opts->read_8);//T states 3 | |
1941 //undocumented N flag behavior | |
1942 //flag set on bit 7 of value written | |
1943 bt_ir(code, 7, opts->gen.scratch1, SZ_B); | |
1944 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); | |
1945 //write to IO (C) | |
1946 zreg_to_native(opts, Z80_C, opts->gen.scratch2); | |
1947 call(code, opts->write_io);//T states 4 | |
1948 //increment HL | |
1949 if (opts->regs[Z80_HL] >= 0) { | |
1950 add_ir(code, 1, opts->regs[Z80_HL], SZ_W); | |
1951 add_rr(code, opts->regs[Z80_L], opts->gen.scratch1, SZ_B); | |
1952 } else { | |
1953 add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B); | |
1954 add_rdispr(code, opts->gen.context_reg, zr_off(Z80_L), opts->gen.scratch1, SZ_B); | |
1955 } | |
1956 //undocumented C and H flag behavior | |
1957 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | |
1958 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); | |
1959 //decrement B | |
1960 if (opts->regs[Z80_B] >= 0) { | |
1961 sub_ir(code, 1, opts->regs[Z80_B], SZ_B); | |
1962 } else { | |
1963 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B); | |
1964 } | |
1965 //undocumented Z and S flag behavior, set based on decrement of B | |
1966 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | |
1967 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | |
1968 //crazy undocumented P/V flag behavior | |
1969 and_ir(code, 7, opts->gen.scratch1, SZ_B); | |
1970 if (opts->regs[Z80_B] >= 0) { | |
1971 //deal with silly x86-64 restrictions on *H registers | |
1972 ror_ir(code, 8, opts->regs[Z80_BC], SZ_W); | |
1973 xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); | |
1974 ror_ir(code, 8, opts->regs[Z80_BC], SZ_W); | |
1975 } else { | |
1976 xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B); | |
1977 } | |
1978 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | |
1979 break; | |
1980 case Z80_OTIR: { | |
1981 code_ptr start = code->cur; | |
1982 cycles(&opts->gen, 9);//T States: 4, 5 | |
1983 //read from (HL) | |
1984 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); | |
1985 call(code, opts->read_8);//T states 3 | |
1986 //undocumented N flag behavior | |
1987 //flag set on bit 7 of value written | |
1988 bt_ir(code, 7, opts->gen.scratch1, SZ_B); | |
1989 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); | |
1990 //write to IO (C) | |
1991 zreg_to_native(opts, Z80_C, opts->gen.scratch2); | |
1992 call(code, opts->write_io);//T states 4 | |
1993 //increment HL | |
1994 if (opts->regs[Z80_HL] >= 0) { | |
1995 add_ir(code, 1, opts->regs[Z80_HL], SZ_W); | |
1996 add_rr(code, opts->regs[Z80_L], opts->gen.scratch1, SZ_B); | |
1997 } else { | |
1998 add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B); | |
1999 add_rdispr(code, opts->gen.context_reg, zr_off(Z80_L), opts->gen.scratch1, SZ_B); | |
2000 } | |
2001 //undocumented C and H flag behavior | |
2002 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | |
2003 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); | |
2004 //decrement B | |
2005 if (opts->regs[Z80_B] >= 0) { | |
2006 sub_ir(code, 1, opts->regs[Z80_B], SZ_B); | |
2007 } else { | |
2008 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B); | |
2009 } | |
2010 //undocumented Z and S flag behavior, set based on decrement of B | |
2011 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | |
2012 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | |
2013 //crazy undocumented P/V flag behavior | |
2014 and_ir(code, 7, opts->gen.scratch1, SZ_B); | |
2015 if (opts->regs[Z80_B] >= 0) { | |
2016 //deal with silly x86-64 restrictions on *H registers | |
2017 ror_ir(code, 8, opts->regs[Z80_BC], SZ_W); | |
2018 xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); | |
2019 ror_ir(code, 8, opts->regs[Z80_BC], SZ_W); | |
2020 } else { | |
2021 xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B); | |
2022 } | |
2023 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | |
2024 if (opts->regs[Z80_B] >= 0) { | |
2025 cmp_ir(code, 0, opts->regs[Z80_B], SZ_B); | |
2026 } else { | |
2027 cmp_irdisp(code, 0, opts->gen.context_reg, zr_off(Z80_B), SZ_B); | |
2028 } | |
2029 code_ptr done = code->cur+1; | |
2030 jcc(code, CC_Z, code->cur+2); | |
2031 cycles(&opts->gen, 5); | |
2032 jmp(code, start); | |
2033 *done = code->cur - (done + 1); | |
2034 break; | |
2035 } | |
1938 case Z80_OUTD: | 2036 case Z80_OUTD: |
1939 case Z80_OTDR:*/ | 2037 cycles(&opts->gen, 9);//T States: 4, 5 |
2038 //read from (HL) | |
2039 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); | |
2040 call(code, opts->read_8);//T states 3 | |
2041 //undocumented N flag behavior | |
2042 //flag set on bit 7 of value written | |
2043 bt_ir(code, 7, opts->gen.scratch1, SZ_B); | |
2044 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); | |
2045 //write to IO (C) | |
2046 zreg_to_native(opts, Z80_C, opts->gen.scratch2); | |
2047 call(code, opts->write_io);//T states 4 | |
2048 //decrement HL | |
2049 if (opts->regs[Z80_HL] >= 0) { | |
2050 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W); | |
2051 add_rr(code, opts->regs[Z80_L], opts->gen.scratch1, SZ_B); | |
2052 } else { | |
2053 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B); | |
2054 add_rdispr(code, opts->gen.context_reg, zr_off(Z80_L), opts->gen.scratch1, SZ_B); | |
2055 } | |
2056 //undocumented C and H flag behavior | |
2057 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | |
2058 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); | |
2059 //decrement B | |
2060 if (opts->regs[Z80_B] >= 0) { | |
2061 sub_ir(code, 1, opts->regs[Z80_B], SZ_B); | |
2062 } else { | |
2063 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B); | |
2064 } | |
2065 //undocumented Z and S flag behavior, set based on decrement of B | |
2066 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | |
2067 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | |
2068 //crazy undocumented P/V flag behavior | |
2069 and_ir(code, 7, opts->gen.scratch1, SZ_B); | |
2070 if (opts->regs[Z80_B] >= 0) { | |
2071 //deal with silly x86-64 restrictions on *H registers | |
2072 ror_ir(code, 8, opts->regs[Z80_BC], SZ_W); | |
2073 xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); | |
2074 ror_ir(code, 8, opts->regs[Z80_BC], SZ_W); | |
2075 } else { | |
2076 xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B); | |
2077 } | |
2078 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | |
2079 break; | |
2080 case Z80_OTDR: { | |
2081 code_ptr start = code->cur; | |
2082 cycles(&opts->gen, 9);//T States: 4, 5 | |
2083 //read from (HL) | |
2084 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); | |
2085 call(code, opts->read_8);//T states 3 | |
2086 //undocumented N flag behavior | |
2087 //flag set on bit 7 of value written | |
2088 bt_ir(code, 7, opts->gen.scratch1, SZ_B); | |
2089 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); | |
2090 //write to IO (C) | |
2091 zreg_to_native(opts, Z80_C, opts->gen.scratch2); | |
2092 call(code, opts->write_io);//T states 4 | |
2093 //increment HL | |
2094 if (opts->regs[Z80_HL] >= 0) { | |
2095 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W); | |
2096 add_rr(code, opts->regs[Z80_L], opts->gen.scratch1, SZ_B); | |
2097 } else { | |
2098 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B); | |
2099 add_rdispr(code, opts->gen.context_reg, zr_off(Z80_L), opts->gen.scratch1, SZ_B); | |
2100 } | |
2101 //undocumented C and H flag behavior | |
2102 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | |
2103 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); | |
2104 //decrement B | |
2105 if (opts->regs[Z80_B] >= 0) { | |
2106 sub_ir(code, 1, opts->regs[Z80_B], SZ_B); | |
2107 } else { | |
2108 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B); | |
2109 } | |
2110 //undocumented Z and S flag behavior, set based on decrement of B | |
2111 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | |
2112 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | |
2113 //crazy undocumented P/V flag behavior | |
2114 and_ir(code, 7, opts->gen.scratch1, SZ_B); | |
2115 if (opts->regs[Z80_B] >= 0) { | |
2116 //deal with silly x86-64 restrictions on *H registers | |
2117 ror_ir(code, 8, opts->regs[Z80_BC], SZ_W); | |
2118 xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); | |
2119 ror_ir(code, 8, opts->regs[Z80_BC], SZ_W); | |
2120 } else { | |
2121 xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B); | |
2122 } | |
2123 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | |
2124 if (opts->regs[Z80_B] >= 0) { | |
2125 cmp_ir(code, 0, opts->regs[Z80_B], SZ_B); | |
2126 } else { | |
2127 cmp_irdisp(code, 0, opts->gen.context_reg, zr_off(Z80_B), SZ_B); | |
2128 } | |
2129 code_ptr done = code->cur+1; | |
2130 jcc(code, CC_Z, code->cur+2); | |
2131 cycles(&opts->gen, 5); | |
2132 jmp(code, start); | |
2133 *done = code->cur - (done + 1); | |
2134 break; | |
2135 } | |
1940 default: { | 2136 default: { |
1941 char disbuf[80]; | 2137 char disbuf[80]; |
1942 z80_disasm(inst, disbuf, address); | 2138 z80_disasm(inst, disbuf, address); |
1943 FILE * f = fopen("zram.bin", "wb"); | 2139 FILE * f = fopen("zram.bin", "wb"); |
1944 fwrite(context->mem_pointers[0], 1, 8 * 1024, f); | 2140 fwrite(context->mem_pointers[0], 1, 8 * 1024, f); |