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);