Mercurial > repos > blastem
comparison m68k_to_x86.c @ 546:90aca661542b
Make references to flags in the M68K core respect the flag_regs options array so that flags can be moved out of registers for the 32-bit port. set/get ccr/sr still need to be updated to support this, but everything else should be done.
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 17 Feb 2014 19:58:37 -0800 |
parents | 67cf0ce57d8d |
children | 3090d016c9e9 |
comparison
equal
deleted
inserted
replaced
545:67cf0ce57d8d | 546:90aca661542b |
---|---|
19 #define LIMIT RBP | 19 #define LIMIT RBP |
20 #define SCRATCH1 RCX | 20 #define SCRATCH1 RCX |
21 #define SCRATCH2 RDI | 21 #define SCRATCH2 RDI |
22 #define CONTEXT RSI | 22 #define CONTEXT RSI |
23 | 23 |
24 /* | |
24 #define FLAG_N RBX | 25 #define FLAG_N RBX |
25 #define FLAG_V BH | 26 #define FLAG_V BH |
26 #define FLAG_Z RDX | 27 #define FLAG_Z RDX |
27 #define FLAG_C DH | 28 #define FLAG_C DH |
29 */ | |
30 enum { | |
31 FLAG_X, | |
32 FLAG_N, | |
33 FLAG_Z, | |
34 FLAG_V, | |
35 FLAG_C | |
36 }; | |
28 | 37 |
29 char disasm_buf[1024]; | 38 char disasm_buf[1024]; |
30 | 39 |
31 m68k_context * sync_components(m68k_context * context, uint32_t address); | 40 m68k_context * sync_components(m68k_context * context, uint32_t address); |
32 | 41 |
59 dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); | 68 dst = cmp_rr(dst, CYCLES, LIMIT, SZ_D); |
60 uint8_t * jmp_off = dst+1; | 69 uint8_t * jmp_off = dst+1; |
61 dst = jcc(dst, CC_NC, dst + 7); | 70 dst = jcc(dst, CC_NC, dst + 7); |
62 dst = call(dst, opts->handle_cycle_limit); | 71 dst = call(dst, opts->handle_cycle_limit); |
63 *jmp_off = dst - (jmp_off+1); | 72 *jmp_off = dst - (jmp_off+1); |
73 return dst; | |
74 } | |
75 | |
76 uint8_t * set_flag(uint8_t * dst, uint8_t val, uint8_t flag, x86_68k_options * opts) | |
77 { | |
78 if (opts->flag_regs[flag] >= 0) { | |
79 dst = mov_ir(dst, val, opts->flag_regs[flag], SZ_B); | |
80 } else { | |
81 int8_t offset = offsetof(m68k_context, flags) + flag; | |
82 if (offset) { | |
83 dst = mov_irdisp8(dst, val, CONTEXT, offset, SZ_B); | |
84 } else { | |
85 dst = mov_irind(dst, val, CONTEXT, SZ_B); | |
86 } | |
87 } | |
88 | |
89 return dst; | |
90 } | |
91 | |
92 uint8_t * set_flag_cond(uint8_t * dst, uint8_t cond, uint8_t flag, x86_68k_options *opts) | |
93 { | |
94 if (opts->flag_regs[flag] >= 0) { | |
95 dst = setcc_r(dst, cond, opts->flag_regs[flag]); | |
96 } else { | |
97 int8_t offset = offsetof(m68k_context, flags) + flag; | |
98 if (offset) { | |
99 dst = setcc_rdisp8(dst, cond, CONTEXT, offset); | |
100 } else { | |
101 dst = setcc_rind(dst, cond, CONTEXT); | |
102 } | |
103 } | |
104 | |
105 return dst; | |
106 } | |
107 | |
108 uint8_t * check_flag(uint8_t *dst, uint8_t flag, x86_68k_options *opts) | |
109 { | |
110 if (opts->flag_regs[flag] >= 0) { | |
111 dst = cmp_ir(dst, 0, opts->flag_regs[flag], SZ_B); | |
112 } else { | |
113 dst = cmp_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, flags) + flag, SZ_B); | |
114 } | |
115 return dst; | |
116 } | |
117 | |
118 uint8_t * flag_to_reg(uint8_t *dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) | |
119 { | |
120 if (opts->flag_regs[flag] >= 0) { | |
121 dst = mov_rr(dst, opts->flag_regs[flag], reg, SZ_B); | |
122 } else { | |
123 int8_t offset = offsetof(m68k_context, flags) + flag; | |
124 if (offset) { | |
125 dst = mov_rdisp8r(dst, CONTEXT, offset, reg, SZ_B); | |
126 } else { | |
127 dst = mov_rindr(dst, CONTEXT, reg, SZ_B); | |
128 } | |
129 } | |
130 return dst; | |
131 } | |
132 | |
133 uint8_t * reg_to_flag(uint8_t *dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) | |
134 { | |
135 if (opts->flag_regs[flag] >= 0) { | |
136 dst = mov_rr(dst, reg, opts->flag_regs[flag], SZ_B); | |
137 } else { | |
138 int8_t offset = offsetof(m68k_context, flags) + flag; | |
139 if (offset) { | |
140 dst = mov_rrdisp8(dst, reg, CONTEXT, offset, SZ_B); | |
141 } else { | |
142 dst = mov_rrind(dst, reg, CONTEXT, SZ_B); | |
143 } | |
144 } | |
145 return dst; | |
146 } | |
147 | |
148 uint8_t * flag_to_flag(uint8_t *dst, uint8_t flag1, uint8_t flag2, x86_68k_options *opts) | |
149 { | |
150 if (opts->flag_regs[flag1] >= 0 && opts->flag_regs[flag2] >= 0) { | |
151 dst = mov_rr(dst, opts->flag_regs[flag1], opts->flag_regs[flag2], SZ_B); | |
152 } else if(opts->flag_regs[flag1] >= 0) { | |
153 dst = mov_rrdisp8(dst, opts->flag_regs[flag1], CONTEXT, offsetof(m68k_context, flags) + flag2, SZ_B); | |
154 } else if (opts->flag_regs[flag2] >= 0) { | |
155 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag1, opts->flag_regs[flag2], SZ_B); | |
156 } else { | |
157 dst = push_r(dst, SCRATCH1); | |
158 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag1, SCRATCH1, SZ_B); | |
159 dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, flags) + flag2, SZ_B); | |
160 dst = pop_r(dst, SCRATCH1); | |
161 } | |
162 return dst; | |
163 } | |
164 | |
165 uint8_t * flag_to_carry(uint8_t *dst, uint8_t flag, x86_68k_options * opts) | |
166 { | |
167 if (opts->flag_regs[flag] >= 0) { | |
168 dst = bt_ir(dst, 0, opts->flag_regs[flag], SZ_B); | |
169 } else { | |
170 dst = bt_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, flags) + flag, SZ_B); | |
171 } | |
172 return dst; | |
173 } | |
174 | |
175 uint8_t * or_flag_to_reg(uint8_t *dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) | |
176 { | |
177 if (opts->flag_regs[flag] >= 0) { | |
178 dst = or_rr(dst, opts->flag_regs[flag], reg, SZ_B); | |
179 } else { | |
180 dst = or_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag, reg, SZ_B); | |
181 } | |
182 return dst; | |
183 } | |
184 | |
185 uint8_t * xor_flag_to_reg(uint8_t *dst, uint8_t flag, uint8_t reg, x86_68k_options *opts) | |
186 { | |
187 if (opts->flag_regs[flag] >= 0) { | |
188 dst = xor_rr(dst, opts->flag_regs[flag], reg, SZ_B); | |
189 } else { | |
190 dst = xor_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag, reg, SZ_B); | |
191 } | |
192 return dst; | |
193 } | |
194 | |
195 uint8_t * xor_flag(uint8_t *dst, uint8_t val, uint8_t flag, x86_68k_options *opts) | |
196 { | |
197 if (opts->flag_regs[flag] >= 0) { | |
198 dst = xor_ir(dst, val, opts->flag_regs[flag], SZ_B); | |
199 } else { | |
200 dst = xor_irdisp8(dst, val, CONTEXT, offsetof(m68k_context, flags) + flag, SZ_B); | |
201 } | |
202 return dst; | |
203 } | |
204 | |
205 uint8_t * cmp_flags(uint8_t *dst, uint8_t flag1, uint8_t flag2, x86_68k_options *opts) | |
206 { | |
207 if (opts->flag_regs[flag1] >= 0 && opts->flag_regs[flag2] >= 0) { | |
208 dst = cmp_rr(dst, opts->flag_regs[flag1], opts->flag_regs[flag2], SZ_B); | |
209 } else if(opts->flag_regs[flag1] >= 0 || opts->flag_regs[flag2] >= 0) { | |
210 if (opts->flag_regs[flag2] >= 0) { | |
211 uint8_t tmp = flag1; | |
212 flag1 = flag2; | |
213 flag2 = tmp; | |
214 } | |
215 dst = cmp_rrdisp8(dst, opts->flag_regs[flag1], CONTEXT, offsetof(m68k_context, flags) + flag2, SZ_B); | |
216 } else { | |
217 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, flags) + flag1, SCRATCH1, SZ_B); | |
218 dst = cmp_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(m68k_context, flags) + flag2, SZ_B); | |
219 } | |
64 return dst; | 220 return dst; |
65 } | 221 } |
66 | 222 |
67 int8_t native_reg(m68k_op_info * op, x86_68k_options * opts) | 223 int8_t native_reg(m68k_op_info * op, x86_68k_options * opts) |
68 { | 224 { |
771 x86_ea src; | 927 x86_ea src; |
772 dst = translate_m68k_src(inst, &src, dst, opts); | 928 dst = translate_m68k_src(inst, &src, dst, opts); |
773 reg = native_reg(&(inst->dst), opts); | 929 reg = native_reg(&(inst->dst), opts); |
774 if (inst->dst.addr_mode != MODE_AREG) { | 930 if (inst->dst.addr_mode != MODE_AREG) { |
775 //update statically set flags | 931 //update statically set flags |
776 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 932 dst = set_flag(dst, 0, FLAG_V, opts); |
777 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 933 dst = set_flag(dst, 0, FLAG_C, opts); |
778 } | 934 } |
779 | 935 |
780 if (inst->dst.addr_mode != MODE_AREG) { | 936 if (inst->dst.addr_mode != MODE_AREG) { |
781 if (src.mode == MODE_REG_DIRECT) { | 937 if (src.mode == MODE_REG_DIRECT) { |
782 flags_reg = src.base; | 938 flags_reg = src.base; |
813 } else { | 969 } else { |
814 dst = mov_irdisp8(dst, src.disp, CONTEXT, reg_offset(&(inst->dst)), size); | 970 dst = mov_irdisp8(dst, src.disp, CONTEXT, reg_offset(&(inst->dst)), size); |
815 } | 971 } |
816 if (inst->dst.addr_mode != MODE_AREG) { | 972 if (inst->dst.addr_mode != MODE_AREG) { |
817 dst = cmp_ir(dst, 0, flags_reg, size); | 973 dst = cmp_ir(dst, 0, flags_reg, size); |
818 dst = setcc_r(dst, CC_Z, FLAG_Z); | 974 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
819 dst = setcc_r(dst, CC_S, FLAG_N); | 975 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
820 } | 976 } |
821 break; | 977 break; |
822 case MODE_AREG_PREDEC: | 978 case MODE_AREG_PREDEC: |
823 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); | 979 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); |
824 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { | 980 if (opts->aregs[inst->dst.params.regs.pri] >= 0) { |
842 } else { | 998 } else { |
843 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 999 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); |
844 } | 1000 } |
845 if (inst->dst.addr_mode != MODE_AREG) { | 1001 if (inst->dst.addr_mode != MODE_AREG) { |
846 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 1002 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); |
847 dst = setcc_r(dst, CC_Z, FLAG_Z); | 1003 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
848 dst = setcc_r(dst, CC_S, FLAG_N); | 1004 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
849 } | 1005 } |
850 switch (inst->extra.size) | 1006 switch (inst->extra.size) |
851 { | 1007 { |
852 case OPSIZE_BYTE: | 1008 case OPSIZE_BYTE: |
853 dst = call(dst, opts->write_8); | 1009 dst = call(dst, opts->write_8); |
885 } else { | 1041 } else { |
886 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 1042 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); |
887 } | 1043 } |
888 if (inst->dst.addr_mode != MODE_AREG) { | 1044 if (inst->dst.addr_mode != MODE_AREG) { |
889 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 1045 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); |
890 dst = setcc_r(dst, CC_Z, FLAG_Z); | 1046 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
891 dst = setcc_r(dst, CC_S, FLAG_N); | 1047 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
892 } | 1048 } |
893 switch (inst->extra.size) | 1049 switch (inst->extra.size) |
894 { | 1050 { |
895 case OPSIZE_BYTE: | 1051 case OPSIZE_BYTE: |
896 dst = call(dst, opts->write_8); | 1052 dst = call(dst, opts->write_8); |
959 } else { | 1115 } else { |
960 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 1116 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); |
961 } | 1117 } |
962 if (inst->dst.addr_mode != MODE_AREG) { | 1118 if (inst->dst.addr_mode != MODE_AREG) { |
963 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 1119 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); |
964 dst = setcc_r(dst, CC_Z, FLAG_Z); | 1120 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
965 dst = setcc_r(dst, CC_S, FLAG_N); | 1121 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
966 } | 1122 } |
967 switch (inst->extra.size) | 1123 switch (inst->extra.size) |
968 { | 1124 { |
969 case OPSIZE_BYTE: | 1125 case OPSIZE_BYTE: |
970 dst = call(dst, opts->write_8); | 1126 dst = call(dst, opts->write_8); |
989 } else { | 1145 } else { |
990 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 1146 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); |
991 } | 1147 } |
992 if (inst->dst.addr_mode != MODE_AREG) { | 1148 if (inst->dst.addr_mode != MODE_AREG) { |
993 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 1149 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); |
994 dst = setcc_r(dst, CC_Z, FLAG_Z); | 1150 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
995 dst = setcc_r(dst, CC_S, FLAG_N); | 1151 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
996 } | 1152 } |
997 switch (inst->extra.size) | 1153 switch (inst->extra.size) |
998 { | 1154 { |
999 case OPSIZE_BYTE: | 1155 case OPSIZE_BYTE: |
1000 dst = call(dst, opts->write_8); | 1156 dst = call(dst, opts->write_8); |
1059 } else { | 1215 } else { |
1060 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); | 1216 dst = mov_ir(dst, src.disp, SCRATCH1, inst->extra.size); |
1061 } | 1217 } |
1062 if (inst->dst.addr_mode != MODE_AREG) { | 1218 if (inst->dst.addr_mode != MODE_AREG) { |
1063 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 1219 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); |
1064 dst = setcc_r(dst, CC_Z, FLAG_Z); | 1220 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
1065 dst = setcc_r(dst, CC_S, FLAG_N); | 1221 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
1066 } | 1222 } |
1067 switch (inst->extra.size) | 1223 switch (inst->extra.size) |
1068 { | 1224 { |
1069 case OPSIZE_BYTE: | 1225 case OPSIZE_BYTE: |
1070 dst = call(dst, opts->write_8); | 1226 dst = call(dst, opts->write_8); |
1094 dst = cycles(dst, BUS); | 1250 dst = cycles(dst, BUS); |
1095 } | 1251 } |
1096 dst = mov_ir(dst, inst->dst.params.immed, SCRATCH2, SZ_D); | 1252 dst = mov_ir(dst, inst->dst.params.immed, SCRATCH2, SZ_D); |
1097 if (inst->dst.addr_mode != MODE_AREG) { | 1253 if (inst->dst.addr_mode != MODE_AREG) { |
1098 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); | 1254 dst = cmp_ir(dst, 0, flags_reg, inst->extra.size); |
1099 dst = setcc_r(dst, CC_Z, FLAG_Z); | 1255 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
1100 dst = setcc_r(dst, CC_S, FLAG_N); | 1256 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
1101 } | 1257 } |
1102 switch (inst->extra.size) | 1258 switch (inst->extra.size) |
1103 { | 1259 { |
1104 case OPSIZE_BYTE: | 1260 case OPSIZE_BYTE: |
1105 dst = call(dst, opts->write_8); | 1261 dst = call(dst, opts->write_8); |
1451 return dst; | 1607 return dst; |
1452 } | 1608 } |
1453 | 1609 |
1454 uint8_t * translate_m68k_clr(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 1610 uint8_t * translate_m68k_clr(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) |
1455 { | 1611 { |
1456 dst = mov_ir(dst, 0, FLAG_N, SZ_B); | 1612 dst = set_flag(dst, 0, FLAG_N, opts); |
1457 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 1613 dst = set_flag(dst, 0, FLAG_V, opts); |
1458 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 1614 dst = set_flag(dst, 0, FLAG_C, opts); |
1459 dst = mov_ir(dst, 1, FLAG_Z, SZ_B); | 1615 dst = set_flag(dst, 1, FLAG_Z, opts); |
1460 int8_t reg = native_reg(&(inst->dst), opts); | 1616 int8_t reg = native_reg(&(inst->dst), opts); |
1461 if (reg >= 0) { | 1617 if (reg >= 0) { |
1462 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 6 : 4)); | 1618 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 6 : 4)); |
1463 return xor_rr(dst, reg, reg, inst->extra.size); | 1619 return xor_rr(dst, reg, reg, inst->extra.size); |
1464 } | 1620 } |
1486 dst = movsx_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, inst->extra.size, dst_size); | 1642 dst = movsx_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, inst->extra.size, dst_size); |
1487 dst = cmp_ir(dst, 0, SCRATCH1, dst_size); | 1643 dst = cmp_ir(dst, 0, SCRATCH1, dst_size); |
1488 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, dst_size); | 1644 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, dst_size); |
1489 } | 1645 } |
1490 inst->extra.size = dst_size; | 1646 inst->extra.size = dst_size; |
1491 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 1647 dst = set_flag(dst, 0, FLAG_V, opts); |
1492 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 1648 dst = set_flag(dst, 0, FLAG_C, opts); |
1493 dst = setcc_r(dst, CC_Z, FLAG_Z); | 1649 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
1494 dst = setcc_r(dst, CC_S, FLAG_N); | 1650 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
1495 //M68K EXT only operates on registers so no need for a call to save result here | 1651 //M68K EXT only operates on registers so no need for a call to save result here |
1496 return dst; | 1652 return dst; |
1497 } | 1653 } |
1498 | 1654 |
1499 uint8_t * translate_m68k_lea(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) | 1655 uint8_t * translate_m68k_lea(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) |
1778 switch (inst->extra.cond) | 1934 switch (inst->extra.cond) |
1779 { | 1935 { |
1780 case COND_HIGH: | 1936 case COND_HIGH: |
1781 cond = CC_Z; | 1937 cond = CC_Z; |
1782 case COND_LOW_SAME: | 1938 case COND_LOW_SAME: |
1783 dst = mov_rr(dst, FLAG_Z, SCRATCH1, SZ_B); | 1939 dst = flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); |
1784 dst = or_rr(dst, FLAG_C, SCRATCH1, SZ_B); | 1940 dst = or_flag_to_reg(dst, FLAG_C, SCRATCH1, opts); |
1785 break; | 1941 break; |
1786 case COND_CARRY_CLR: | 1942 case COND_CARRY_CLR: |
1787 cond = CC_Z; | 1943 cond = CC_Z; |
1788 case COND_CARRY_SET: | 1944 case COND_CARRY_SET: |
1789 dst = cmp_ir(dst, 0, FLAG_C, SZ_B); | 1945 dst = check_flag(dst, FLAG_C, opts); |
1790 break; | 1946 break; |
1791 case COND_NOT_EQ: | 1947 case COND_NOT_EQ: |
1792 cond = CC_Z; | 1948 cond = CC_Z; |
1793 case COND_EQ: | 1949 case COND_EQ: |
1794 dst = cmp_ir(dst, 0, FLAG_Z, SZ_B); | 1950 dst = check_flag(dst, FLAG_Z, opts); |
1795 break; | 1951 break; |
1796 case COND_OVERF_CLR: | 1952 case COND_OVERF_CLR: |
1797 cond = CC_Z; | 1953 cond = CC_Z; |
1798 case COND_OVERF_SET: | 1954 case COND_OVERF_SET: |
1799 dst = cmp_ir(dst, 0, FLAG_V, SZ_B); | 1955 dst = check_flag(dst, FLAG_V, opts); |
1800 break; | 1956 break; |
1801 case COND_PLUS: | 1957 case COND_PLUS: |
1802 cond = CC_Z; | 1958 cond = CC_Z; |
1803 case COND_MINUS: | 1959 case COND_MINUS: |
1804 dst = cmp_ir(dst, 0, FLAG_N, SZ_B); | 1960 dst = check_flag(dst, FLAG_N, opts); |
1805 break; | 1961 break; |
1806 case COND_GREATER_EQ: | 1962 case COND_GREATER_EQ: |
1807 cond = CC_Z; | 1963 cond = CC_Z; |
1808 case COND_LESS: | 1964 case COND_LESS: |
1809 dst = cmp_rr(dst, FLAG_N, FLAG_V, SZ_B); | 1965 dst = cmp_flags(dst, FLAG_N, FLAG_V, opts); |
1810 break; | 1966 break; |
1811 case COND_GREATER: | 1967 case COND_GREATER: |
1812 cond = CC_Z; | 1968 cond = CC_Z; |
1813 case COND_LESS_EQ: | 1969 case COND_LESS_EQ: |
1814 dst = mov_rr(dst, FLAG_V, SCRATCH1, SZ_B); | 1970 dst = flag_to_reg(dst, FLAG_V, SCRATCH1, opts); |
1815 dst = xor_rr(dst, FLAG_N, SCRATCH1, SZ_B); | 1971 dst = xor_flag_to_reg(dst, FLAG_N, SCRATCH1, opts); |
1816 dst = or_rr(dst, FLAG_Z, SCRATCH1, SZ_B); | 1972 dst = or_flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); |
1817 break; | 1973 break; |
1818 } | 1974 } |
1819 if (!dest_addr) { | 1975 if (!dest_addr) { |
1820 opts->deferred = defer_address(opts->deferred, after + disp, dst + 2); | 1976 opts->deferred = defer_address(opts->deferred, after + disp, dst + 2); |
1821 //dummy address to be replaced later, make sure it generates a 4-byte displacement | 1977 //dummy address to be replaced later, make sure it generates a 4-byte displacement |
1848 switch (cond) | 2004 switch (cond) |
1849 { | 2005 { |
1850 case COND_HIGH: | 2006 case COND_HIGH: |
1851 cc = CC_Z; | 2007 cc = CC_Z; |
1852 case COND_LOW_SAME: | 2008 case COND_LOW_SAME: |
1853 dst = mov_rr(dst, FLAG_Z, SCRATCH1, SZ_B); | 2009 dst = flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); |
1854 dst = or_rr(dst, FLAG_C, SCRATCH1, SZ_B); | 2010 dst = or_flag_to_reg(dst, FLAG_C, SCRATCH1, opts); |
1855 break; | 2011 break; |
1856 case COND_CARRY_CLR: | 2012 case COND_CARRY_CLR: |
1857 cc = CC_Z; | 2013 cc = CC_Z; |
1858 case COND_CARRY_SET: | 2014 case COND_CARRY_SET: |
1859 dst = cmp_ir(dst, 0, FLAG_C, SZ_B); | 2015 dst = check_flag(dst, FLAG_C, opts); |
1860 break; | 2016 break; |
1861 case COND_NOT_EQ: | 2017 case COND_NOT_EQ: |
1862 cc = CC_Z; | 2018 cc = CC_Z; |
1863 case COND_EQ: | 2019 case COND_EQ: |
1864 dst = cmp_ir(dst, 0, FLAG_Z, SZ_B); | 2020 dst = check_flag(dst, FLAG_Z, opts); |
1865 break; | 2021 break; |
1866 case COND_OVERF_CLR: | 2022 case COND_OVERF_CLR: |
1867 cc = CC_Z; | 2023 cc = CC_Z; |
1868 case COND_OVERF_SET: | 2024 case COND_OVERF_SET: |
1869 dst = cmp_ir(dst, 0, FLAG_V, SZ_B); | 2025 dst = check_flag(dst, FLAG_V, opts); |
1870 break; | 2026 break; |
1871 case COND_PLUS: | 2027 case COND_PLUS: |
1872 cc = CC_Z; | 2028 cc = CC_Z; |
1873 case COND_MINUS: | 2029 case COND_MINUS: |
1874 dst = cmp_ir(dst, 0, FLAG_N, SZ_B); | 2030 dst = check_flag(dst, FLAG_N, opts); |
1875 break; | 2031 break; |
1876 case COND_GREATER_EQ: | 2032 case COND_GREATER_EQ: |
1877 cc = CC_Z; | 2033 cc = CC_Z; |
1878 case COND_LESS: | 2034 case COND_LESS: |
1879 dst = cmp_rr(dst, FLAG_N, FLAG_V, SZ_B); | 2035 dst = cmp_flags(dst, FLAG_N, FLAG_V, opts); |
1880 break; | 2036 break; |
1881 case COND_GREATER: | 2037 case COND_GREATER: |
1882 cc = CC_Z; | 2038 cc = CC_Z; |
1883 case COND_LESS_EQ: | 2039 case COND_LESS_EQ: |
1884 dst = mov_rr(dst, FLAG_V, SCRATCH1, SZ_B); | 2040 dst = flag_to_reg(dst, FLAG_V, SCRATCH1, opts); |
1885 dst = xor_rr(dst, FLAG_N, SCRATCH1, SZ_B); | 2041 dst = xor_flag_to_reg(dst, FLAG_N, SCRATCH1, opts); |
1886 dst = or_rr(dst, FLAG_Z, SCRATCH1, SZ_B); | 2042 dst = or_flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); |
1887 break; | 2043 break; |
1888 } | 2044 } |
1889 uint8_t *true_off = dst + 1; | 2045 uint8_t *true_off = dst + 1; |
1890 dst = jcc(dst, cc, dst+2); | 2046 dst = jcc(dst, cc, dst+2); |
1891 dst = cycles(dst, BUS); | 2047 dst = cycles(dst, BUS); |
2258 switch (inst->extra.cond) | 2414 switch (inst->extra.cond) |
2259 { | 2415 { |
2260 case COND_HIGH: | 2416 case COND_HIGH: |
2261 cond = CC_Z; | 2417 cond = CC_Z; |
2262 case COND_LOW_SAME: | 2418 case COND_LOW_SAME: |
2263 dst = mov_rr(dst, FLAG_Z, SCRATCH1, SZ_B); | 2419 dst = flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); |
2264 dst = or_rr(dst, FLAG_C, SCRATCH1, SZ_B); | 2420 dst = or_flag_to_reg(dst, FLAG_C, SCRATCH1, opts); |
2265 break; | 2421 break; |
2266 case COND_CARRY_CLR: | 2422 case COND_CARRY_CLR: |
2267 cond = CC_Z; | 2423 cond = CC_Z; |
2268 case COND_CARRY_SET: | 2424 case COND_CARRY_SET: |
2269 dst = cmp_ir(dst, 0, FLAG_C, SZ_B); | 2425 dst = check_flag(dst, FLAG_C, opts); |
2270 break; | 2426 break; |
2271 case COND_NOT_EQ: | 2427 case COND_NOT_EQ: |
2272 cond = CC_Z; | 2428 cond = CC_Z; |
2273 case COND_EQ: | 2429 case COND_EQ: |
2274 dst = cmp_ir(dst, 0, FLAG_Z, SZ_B); | 2430 dst = check_flag(dst, FLAG_Z, opts); |
2275 break; | 2431 break; |
2276 case COND_OVERF_CLR: | 2432 case COND_OVERF_CLR: |
2277 cond = CC_Z; | 2433 cond = CC_Z; |
2278 case COND_OVERF_SET: | 2434 case COND_OVERF_SET: |
2279 dst = cmp_ir(dst, 0, FLAG_V, SZ_B); | 2435 dst = check_flag(dst, FLAG_V, opts); |
2280 break; | 2436 break; |
2281 case COND_PLUS: | 2437 case COND_PLUS: |
2282 cond = CC_Z; | 2438 cond = CC_Z; |
2283 case COND_MINUS: | 2439 case COND_MINUS: |
2284 dst = cmp_ir(dst, 0, FLAG_N, SZ_B); | 2440 dst = check_flag(dst, FLAG_N, opts); |
2285 break; | 2441 break; |
2286 case COND_GREATER_EQ: | 2442 case COND_GREATER_EQ: |
2287 cond = CC_Z; | 2443 cond = CC_Z; |
2288 case COND_LESS: | 2444 case COND_LESS: |
2289 dst = cmp_rr(dst, FLAG_N, FLAG_V, SZ_B); | 2445 dst = cmp_flags(dst, FLAG_N, FLAG_V, opts); |
2290 break; | 2446 break; |
2291 case COND_GREATER: | 2447 case COND_GREATER: |
2292 cond = CC_Z; | 2448 cond = CC_Z; |
2293 case COND_LESS_EQ: | 2449 case COND_LESS_EQ: |
2294 dst = mov_rr(dst, FLAG_V, SCRATCH1, SZ_B); | 2450 dst = flag_to_reg(dst, FLAG_V, SCRATCH1, opts); |
2295 dst = xor_rr(dst, FLAG_N, SCRATCH1, SZ_B); | 2451 dst = xor_flag_to_reg(dst, FLAG_N, SCRATCH1, opts); |
2296 dst = or_rr(dst, FLAG_Z, SCRATCH1, SZ_B); | 2452 dst = or_flag_to_reg(dst, FLAG_Z, SCRATCH1, opts); |
2297 break; | 2453 break; |
2298 } | 2454 } |
2299 skip_loc = dst + 1; | 2455 skip_loc = dst + 1; |
2300 dst = jcc(dst, cond, dst + 2); | 2456 dst = jcc(dst, cond, dst + 2); |
2301 } | 2457 } |
2490 dst = cmp_ir(dst, src_op.disp, dst_op.base, size); | 2646 dst = cmp_ir(dst, src_op.disp, dst_op.base, size); |
2491 } else { | 2647 } else { |
2492 dst = cmp_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, size); | 2648 dst = cmp_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, size); |
2493 } | 2649 } |
2494 } | 2650 } |
2495 dst = setcc_r(dst, CC_C, FLAG_C); | 2651 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
2496 dst = setcc_r(dst, CC_Z, FLAG_Z); | 2652 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
2497 dst = setcc_r(dst, CC_S, FLAG_N); | 2653 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
2498 dst = setcc_r(dst, CC_O, FLAG_V); | 2654 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); |
2499 return dst; | 2655 return dst; |
2500 } | 2656 } |
2501 | 2657 |
2502 typedef uint8_t * (*shift_ir_t)(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size); | 2658 typedef uint8_t * (*shift_ir_t)(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size); |
2503 typedef uint8_t * (*shift_irdisp8_t)(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t disp, uint8_t size); | 2659 typedef uint8_t * (*shift_irdisp8_t)(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t disp, uint8_t size); |
2515 dst = shift_ir(dst, 1, dst_op->base, SZ_W); | 2671 dst = shift_ir(dst, 1, dst_op->base, SZ_W); |
2516 } else { | 2672 } else { |
2517 dst = cycles(dst, inst->extra.size == OPSIZE_LONG ? 8 : 6); | 2673 dst = cycles(dst, inst->extra.size == OPSIZE_LONG ? 8 : 6); |
2518 if (src_op->mode == MODE_IMMED) { | 2674 if (src_op->mode == MODE_IMMED) { |
2519 if (src_op->disp != 1 && inst->op == M68K_ASL) { | 2675 if (src_op->disp != 1 && inst->op == M68K_ASL) { |
2520 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 2676 dst = set_flag(dst, 0, FLAG_V, opts); |
2521 for (int i = 0; i < src_op->disp; i++) { | 2677 for (int i = 0; i < src_op->disp; i++) { |
2522 if (dst_op->mode == MODE_REG_DIRECT) { | 2678 if (dst_op->mode == MODE_REG_DIRECT) { |
2523 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); | 2679 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); |
2524 } else { | 2680 } else { |
2525 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); | 2681 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); |
2526 } | 2682 } |
2527 //dst = setcc_r(dst, CC_O, FLAG_V); | 2683 //dst = setcc_r(dst, CC_O, FLAG_V); |
2528 dst = jcc(dst, CC_NO, dst+4); | 2684 uint8_t *after_flag_set = dst+1; |
2529 dst = mov_ir(dst, 1, FLAG_V, SZ_B); | 2685 dst = jcc(dst, CC_NO, dst+2); |
2686 dst = set_flag(dst, 1, FLAG_V, opts); | |
2687 *after_flag_set = dst - (after_flag_set+1); | |
2530 } | 2688 } |
2531 } else { | 2689 } else { |
2532 if (dst_op->mode == MODE_REG_DIRECT) { | 2690 if (dst_op->mode == MODE_REG_DIRECT) { |
2533 dst = shift_ir(dst, src_op->disp, dst_op->base, inst->extra.size); | 2691 dst = shift_ir(dst, src_op->disp, dst_op->base, inst->extra.size); |
2534 } else { | 2692 } else { |
2535 dst = shift_irdisp8(dst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); | 2693 dst = shift_irdisp8(dst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); |
2536 } | 2694 } |
2537 dst = setcc_r(dst, CC_O, FLAG_V); | 2695 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); |
2538 } | 2696 } |
2539 } else { | 2697 } else { |
2540 if (src_op->base != RCX) { | 2698 if (src_op->base != RCX) { |
2541 if (src_op->mode == MODE_REG_DIRECT) { | 2699 if (src_op->mode == MODE_REG_DIRECT) { |
2542 dst = mov_rr(dst, src_op->base, RCX, SZ_B); | 2700 dst = mov_rr(dst, src_op->base, RCX, SZ_B); |
2552 if (dst_op->mode == MODE_REG_DIRECT) { | 2710 if (dst_op->mode == MODE_REG_DIRECT) { |
2553 dst = cmp_ir(dst, 0, dst_op->base, inst->extra.size); | 2711 dst = cmp_ir(dst, 0, dst_op->base, inst->extra.size); |
2554 } else { | 2712 } else { |
2555 dst = cmp_irdisp8(dst, 0, dst_op->base, dst_op->disp, inst->extra.size); | 2713 dst = cmp_irdisp8(dst, 0, dst_op->base, dst_op->disp, inst->extra.size); |
2556 } | 2714 } |
2557 dst = setcc_r(dst, CC_Z, FLAG_Z); | 2715 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
2558 dst = setcc_r(dst, CC_S, FLAG_N); | 2716 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
2559 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 2717 dst = set_flag(dst, 0, FLAG_C, opts); |
2560 //For other instructions, this flag will be set below | 2718 //For other instructions, this flag will be set below |
2561 if (inst->op == M68K_ASL) { | 2719 if (inst->op == M68K_ASL) { |
2562 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 2720 dst = set_flag(dst, 0, FLAG_V, opts); |
2563 } | 2721 } |
2564 z_off = dst+1; | 2722 z_off = dst+1; |
2565 dst = jmp(dst, dst+2); | 2723 dst = jmp(dst, dst+2); |
2566 *nz_off = dst - (nz_off + 1); | 2724 *nz_off = dst - (nz_off + 1); |
2567 //add 2 cycles for every bit shifted | 2725 //add 2 cycles for every bit shifted |
2568 dst = add_rr(dst, RCX, CYCLES, SZ_D); | 2726 dst = add_rr(dst, RCX, CYCLES, SZ_D); |
2569 dst = add_rr(dst, RCX, CYCLES, SZ_D); | 2727 dst = add_rr(dst, RCX, CYCLES, SZ_D); |
2570 if (inst->op == M68K_ASL) { | 2728 if (inst->op == M68K_ASL) { |
2571 //ASL has Overflow flag behavior that depends on all of the bits shifted through the MSB | 2729 //ASL has Overflow flag behavior that depends on all of the bits shifted through the MSB |
2572 //Easiest way to deal with this is to shift one bit at a time | 2730 //Easiest way to deal with this is to shift one bit at a time |
2573 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 2731 dst = set_flag(dst, 0, FLAG_V, opts); |
2574 uint8_t * loop_start = dst; | 2732 uint8_t * loop_start = dst; |
2575 if (dst_op->mode == MODE_REG_DIRECT) { | 2733 if (dst_op->mode == MODE_REG_DIRECT) { |
2576 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); | 2734 dst = shift_ir(dst, 1, dst_op->base, inst->extra.size); |
2577 } else { | 2735 } else { |
2578 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); | 2736 dst = shift_irdisp8(dst, 1, dst_op->base, dst_op->disp, inst->extra.size); |
2579 } | 2737 } |
2580 //dst = setcc_r(dst, CC_O, FLAG_V); | 2738 //dst = setcc_r(dst, CC_O, FLAG_V); |
2581 dst = jcc(dst, CC_NO, dst+4); | 2739 uint8_t *after_flag_set = dst+1; |
2582 dst = mov_ir(dst, 1, FLAG_V, SZ_B); | 2740 dst = jcc(dst, CC_NO, dst+2); |
2741 dst = set_flag(dst, 1, FLAG_V, opts); | |
2742 *after_flag_set = dst - (after_flag_set+1); | |
2583 dst = loop(dst, loop_start); | 2743 dst = loop(dst, loop_start); |
2584 } else { | 2744 } else { |
2585 //x86 shifts modulo 32 for operand sizes less than 64-bits | 2745 //x86 shifts modulo 32 for operand sizes less than 64-bits |
2586 //but M68K shifts modulo 64, so we need to check for large shifts here | 2746 //but M68K shifts modulo 64, so we need to check for large shifts here |
2587 dst = cmp_ir(dst, 32, RCX, SZ_B); | 2747 dst = cmp_ir(dst, 32, RCX, SZ_B); |
2588 uint8_t * norm_shift_off = dst + 1; | 2748 uint8_t * norm_shift_off = dst + 1; |
2589 dst = jcc(dst, CC_L, dst+2); | 2749 dst = jcc(dst, CC_L, dst+2); |
2590 if (special) { | 2750 if (special) { |
2751 uint8_t *after_flag_set = NULL; | |
2591 if (inst->extra.size == OPSIZE_LONG) { | 2752 if (inst->extra.size == OPSIZE_LONG) { |
2592 uint8_t * neq_32_off = dst + 1; | 2753 uint8_t * neq_32_off = dst + 1; |
2593 dst = jcc(dst, CC_NZ, dst+2); | 2754 dst = jcc(dst, CC_NZ, dst+2); |
2594 | 2755 |
2595 //set the carry bit to the lsb | 2756 //set the carry bit to the lsb |
2596 if (dst_op->mode == MODE_REG_DIRECT) { | 2757 if (dst_op->mode == MODE_REG_DIRECT) { |
2597 dst = special(dst, 1, dst_op->base, SZ_D); | 2758 dst = special(dst, 1, dst_op->base, SZ_D); |
2598 } else { | 2759 } else { |
2599 dst = special_disp8(dst, 1, dst_op->base, dst_op->disp, SZ_D); | 2760 dst = special_disp8(dst, 1, dst_op->base, dst_op->disp, SZ_D); |
2600 } | 2761 } |
2601 dst = setcc_r(dst, CC_C, FLAG_C); | 2762 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
2602 dst = jmp(dst, dst+4); | 2763 after_flag_set = dst+1; |
2764 dst = jmp(dst, dst+2); | |
2603 *neq_32_off = dst - (neq_32_off+1); | 2765 *neq_32_off = dst - (neq_32_off+1); |
2604 } | 2766 } |
2605 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 2767 dst = set_flag(dst, 0, FLAG_C, opts); |
2606 dst = mov_ir(dst, 1, FLAG_Z, SZ_B); | 2768 if (after_flag_set) { |
2607 dst = mov_ir(dst, 0, FLAG_N, SZ_B); | 2769 *after_flag_set = dst - (after_flag_set+1); |
2770 } | |
2771 dst = set_flag(dst, 1, FLAG_Z, opts); | |
2772 dst = set_flag(dst, 0, FLAG_N, opts); | |
2608 if (dst_op->mode == MODE_REG_DIRECT) { | 2773 if (dst_op->mode == MODE_REG_DIRECT) { |
2609 dst = xor_rr(dst, dst_op->base, dst_op->base, inst->extra.size); | 2774 dst = xor_rr(dst, dst_op->base, dst_op->base, inst->extra.size); |
2610 } else { | 2775 } else { |
2611 dst = mov_irdisp8(dst, 0, dst_op->base, dst_op->disp, inst->extra.size); | 2776 dst = mov_irdisp8(dst, 0, dst_op->base, dst_op->disp, inst->extra.size); |
2612 } | 2777 } |
2633 | 2798 |
2634 } | 2799 } |
2635 if (!special && end_off) { | 2800 if (!special && end_off) { |
2636 *end_off = dst - (end_off + 1); | 2801 *end_off = dst - (end_off + 1); |
2637 } | 2802 } |
2638 dst = setcc_r(dst, CC_C, FLAG_C); | 2803 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
2639 dst = setcc_r(dst, CC_Z, FLAG_Z); | 2804 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
2640 dst = setcc_r(dst, CC_S, FLAG_N); | 2805 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
2641 if (special && end_off) { | 2806 if (special && end_off) { |
2642 *end_off = dst - (end_off + 1); | 2807 *end_off = dst - (end_off + 1); |
2643 } | 2808 } |
2644 //set X flag to same as C flag | 2809 //set X flag to same as C flag |
2645 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 2810 if (opts->flag_regs[FLAG_C] >= 0) { |
2811 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | |
2812 } else { | |
2813 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | |
2814 } | |
2646 if (z_off) { | 2815 if (z_off) { |
2647 *z_off = dst - (z_off + 1); | 2816 *z_off = dst - (z_off + 1); |
2648 } | 2817 } |
2649 if (inst->op != M68K_ASL) { | 2818 if (inst->op != M68K_ASL) { |
2650 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 2819 dst = set_flag(dst, 0, FLAG_V, opts); |
2651 } | 2820 } |
2652 if (inst->src.addr_mode == MODE_UNUSED) { | 2821 if (inst->src.addr_mode == MODE_UNUSED) { |
2653 dst = m68k_save_result(inst, dst, opts); | 2822 dst = m68k_save_result(inst, dst, opts); |
2654 } | 2823 } |
2655 return dst; | 2824 return dst; |
2724 dst = mov_rr(dst, dst_op.base, SCRATCH1, SZ_B); | 2893 dst = mov_rr(dst, dst_op.base, SCRATCH1, SZ_B); |
2725 } else { | 2894 } else { |
2726 dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, SZ_B); | 2895 dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, SZ_B); |
2727 } | 2896 } |
2728 } | 2897 } |
2729 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); | 2898 dst = flag_to_carry(dst, FLAG_X, opts); |
2730 dst = jcc(dst, CC_NC, dst+5); | 2899 dst = jcc(dst, CC_NC, dst+5); |
2731 dst = add_ir(dst, 1, SCRATCH1, SZ_B); | 2900 dst = add_ir(dst, 1, SCRATCH1, SZ_B); |
2732 dst = call(dst, (uint8_t *)bcd_add); | 2901 dst = call(dst, (uint8_t *)bcd_add); |
2733 dst = mov_rr(dst, CH, FLAG_C, SZ_B); | 2902 dst = reg_to_flag(dst, CH, FLAG_C, opts); |
2734 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 2903 dst = reg_to_flag(dst, CH, FLAG_X, opts); |
2735 dst = cmp_ir(dst, 0, SCRATCH1, SZ_B); | 2904 dst = cmp_ir(dst, 0, SCRATCH1, SZ_B); |
2736 dst = jcc(dst, CC_Z, dst+4); | 2905 dst = jcc(dst, CC_Z, dst+4); |
2737 dst = mov_ir(dst, 0, FLAG_Z, SZ_B); | 2906 dst = set_flag(dst, 0, FLAG_Z, opts); |
2738 if (dst_op.base != SCRATCH1) { | 2907 if (dst_op.base != SCRATCH1) { |
2739 if (dst_op.mode == MODE_REG_DIRECT) { | 2908 if (dst_op.mode == MODE_REG_DIRECT) { |
2740 dst = mov_rr(dst, SCRATCH1, dst_op.base, SZ_B); | 2909 dst = mov_rr(dst, SCRATCH1, dst_op.base, SZ_B); |
2741 } else { | 2910 } else { |
2742 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_B); | 2911 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_B); |
2761 } else { | 2930 } else { |
2762 dst = add_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, size); | 2931 dst = add_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, size); |
2763 } | 2932 } |
2764 } | 2933 } |
2765 if (inst->dst.addr_mode != MODE_AREG) { | 2934 if (inst->dst.addr_mode != MODE_AREG) { |
2766 dst = setcc_r(dst, CC_C, FLAG_C); | 2935 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
2767 dst = setcc_r(dst, CC_Z, FLAG_Z); | 2936 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
2768 dst = setcc_r(dst, CC_S, FLAG_N); | 2937 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
2769 dst = setcc_r(dst, CC_O, FLAG_V); | 2938 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); |
2770 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 2939 if (opts->flag_regs[FLAG_C] >= 0) { |
2940 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | |
2941 } else { | |
2942 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | |
2943 } | |
2771 } | 2944 } |
2772 dst = m68k_save_result(inst, dst, opts); | 2945 dst = m68k_save_result(inst, dst, opts); |
2773 break; | 2946 break; |
2774 case M68K_ADDX: | 2947 case M68K_ADDX: { |
2775 dst = cycles(dst, BUS); | 2948 dst = cycles(dst, BUS); |
2776 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); | 2949 dst = flag_to_carry(dst, FLAG_X, opts); |
2777 if (src_op.mode == MODE_REG_DIRECT) { | 2950 if (src_op.mode == MODE_REG_DIRECT) { |
2778 if (dst_op.mode == MODE_REG_DIRECT) { | 2951 if (dst_op.mode == MODE_REG_DIRECT) { |
2779 dst = adc_rr(dst, src_op.base, dst_op.base, inst->extra.size); | 2952 dst = adc_rr(dst, src_op.base, dst_op.base, inst->extra.size); |
2780 } else { | 2953 } else { |
2781 dst = adc_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); | 2954 dst = adc_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); |
2787 dst = adc_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 2960 dst = adc_ir(dst, src_op.disp, dst_op.base, inst->extra.size); |
2788 } else { | 2961 } else { |
2789 dst = adc_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 2962 dst = adc_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
2790 } | 2963 } |
2791 } | 2964 } |
2792 dst = setcc_r(dst, CC_C, FLAG_C); | 2965 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
2793 dst = jcc(dst, CC_Z, dst+4); | 2966 |
2794 dst = mov_ir(dst, 0, FLAG_Z, SZ_B); | 2967 uint8_t *after_flag_set = dst+1; |
2795 dst = setcc_r(dst, CC_S, FLAG_N); | 2968 dst = jcc(dst, CC_Z, dst+2); |
2796 dst = setcc_r(dst, CC_O, FLAG_V); | 2969 dst = set_flag(dst, 0, FLAG_Z, opts); |
2797 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 2970 *after_flag_set = dst - (after_flag_set+1); |
2971 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | |
2972 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | |
2973 if (opts->flag_regs[FLAG_C] >= 0) { | |
2974 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | |
2975 } else { | |
2976 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | |
2977 } | |
2798 dst = m68k_save_result(inst, dst, opts); | 2978 dst = m68k_save_result(inst, dst, opts); |
2799 break; | 2979 break; |
2980 } | |
2800 case M68K_AND: | 2981 case M68K_AND: |
2801 dst = cycles(dst, BUS); | 2982 dst = cycles(dst, BUS); |
2802 if (src_op.mode == MODE_REG_DIRECT) { | 2983 if (src_op.mode == MODE_REG_DIRECT) { |
2803 if (dst_op.mode == MODE_REG_DIRECT) { | 2984 if (dst_op.mode == MODE_REG_DIRECT) { |
2804 dst = and_rr(dst, src_op.base, dst_op.base, inst->extra.size); | 2985 dst = and_rr(dst, src_op.base, dst_op.base, inst->extra.size); |
2812 dst = and_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 2993 dst = and_ir(dst, src_op.disp, dst_op.base, inst->extra.size); |
2813 } else { | 2994 } else { |
2814 dst = and_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 2995 dst = and_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
2815 } | 2996 } |
2816 } | 2997 } |
2817 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 2998 dst = set_flag(dst, 0, FLAG_C, opts); |
2818 dst = setcc_r(dst, CC_Z, FLAG_Z); | 2999 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
2819 dst = setcc_r(dst, CC_S, FLAG_N); | 3000 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
2820 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 3001 dst = set_flag(dst, 0, FLAG_V, opts); |
2821 dst = m68k_save_result(inst, dst, opts); | 3002 dst = m68k_save_result(inst, dst, opts); |
2822 break; | 3003 break; |
2823 case M68K_ANDI_CCR: | 3004 case M68K_ANDI_CCR: |
2824 case M68K_ANDI_SR: | 3005 case M68K_ANDI_SR: |
2825 dst = cycles(dst, 20); | 3006 dst = cycles(dst, 20); |
2826 //TODO: If ANDI to SR, trap if not in supervisor mode | 3007 //TODO: If ANDI to SR, trap if not in supervisor mode |
2827 if (!(inst->src.params.immed & 0x1)) { | 3008 if (!(inst->src.params.immed & 0x1)) { |
2828 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 3009 dst = set_flag(dst, 0, FLAG_C, opts); |
2829 } | 3010 } |
2830 if (!(inst->src.params.immed & 0x2)) { | 3011 if (!(inst->src.params.immed & 0x2)) { |
2831 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 3012 dst = set_flag(dst, 0, FLAG_V, opts); |
2832 } | 3013 } |
2833 if (!(inst->src.params.immed & 0x4)) { | 3014 if (!(inst->src.params.immed & 0x4)) { |
2834 dst = mov_ir(dst, 0, FLAG_Z, SZ_B); | 3015 dst = set_flag(dst, 0, FLAG_Z, opts); |
2835 } | 3016 } |
2836 if (!(inst->src.params.immed & 0x8)) { | 3017 if (!(inst->src.params.immed & 0x8)) { |
2837 dst = mov_ir(dst, 0, FLAG_N, SZ_B); | 3018 dst = set_flag(dst, 0, FLAG_N, opts); |
2838 } | 3019 } |
2839 if (!(inst->src.params.immed & 0x10)) { | 3020 if (!(inst->src.params.immed & 0x10)) { |
2840 dst = mov_irind(dst, 0, CONTEXT, SZ_B); | 3021 dst = set_flag(dst, 0, FLAG_X, opts); |
2841 } | 3022 } |
2842 if (inst->op == M68K_ANDI_SR) { | 3023 if (inst->op == M68K_ANDI_SR) { |
2843 dst = and_irdisp8(dst, inst->src.params.immed >> 8, CONTEXT, offsetof(m68k_context, status), SZ_B); | 3024 dst = and_irdisp8(dst, inst->src.params.immed >> 8, CONTEXT, offsetof(m68k_context, status), SZ_B); |
2844 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { | 3025 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { |
2845 //leave supervisor mode | 3026 //leave supervisor mode |
2968 dst = pop_r(dst, SCRATCH2); | 3149 dst = pop_r(dst, SCRATCH2); |
2969 } | 3150 } |
2970 } | 3151 } |
2971 //x86 sets the carry flag to the value of the bit tested | 3152 //x86 sets the carry flag to the value of the bit tested |
2972 //68K sets the zero flag to the complement of the bit tested | 3153 //68K sets the zero flag to the complement of the bit tested |
2973 dst = setcc_r(dst, CC_NC, FLAG_Z); | 3154 dst = set_flag_cond(dst, CC_NC, FLAG_Z, opts); |
2974 if (inst->op != M68K_BTST) { | 3155 if (inst->op != M68K_BTST) { |
2975 dst = m68k_save_result(inst, dst, opts); | 3156 dst = m68k_save_result(inst, dst, opts); |
2976 } | 3157 } |
2977 break; | 3158 break; |
2978 case M68K_CHK: | 3159 case M68K_CHK: |
3000 default: | 3181 default: |
3001 isize = 2; | 3182 isize = 2; |
3002 } | 3183 } |
3003 uint8_t * passed = dst+1; | 3184 uint8_t * passed = dst+1; |
3004 dst = jcc(dst, CC_GE, dst+2); | 3185 dst = jcc(dst, CC_GE, dst+2); |
3005 dst = mov_ir(dst, 1, FLAG_N, SZ_B); | 3186 dst = set_flag(dst, 1, FLAG_N, opts); |
3006 dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D); | 3187 dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D); |
3007 dst = mov_ir(dst, inst->address+isize, SCRATCH1, SZ_D); | 3188 dst = mov_ir(dst, inst->address+isize, SCRATCH1, SZ_D); |
3008 dst = jmp(dst, opts->trap); | 3189 dst = jmp(dst, opts->trap); |
3009 *passed = dst - (passed+1); | 3190 *passed = dst - (passed+1); |
3010 if (dst_op.mode == MODE_REG_DIRECT) { | 3191 if (dst_op.mode == MODE_REG_DIRECT) { |
3022 dst = cmp_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3203 dst = cmp_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3023 } | 3204 } |
3024 } | 3205 } |
3025 passed = dst+1; | 3206 passed = dst+1; |
3026 dst = jcc(dst, CC_LE, dst+2); | 3207 dst = jcc(dst, CC_LE, dst+2); |
3027 dst = mov_ir(dst, 0, FLAG_N, SZ_B); | 3208 dst = set_flag(dst, 0, FLAG_N, opts); |
3028 dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D); | 3209 dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D); |
3029 dst = mov_ir(dst, inst->address+isize, SCRATCH1, SZ_D); | 3210 dst = mov_ir(dst, inst->address+isize, SCRATCH1, SZ_D); |
3030 dst = jmp(dst, opts->trap); | 3211 dst = jmp(dst, opts->trap); |
3031 *passed = dst - (passed+1); | 3212 *passed = dst - (passed+1); |
3032 dst = cycles(dst, 4); | 3213 dst = cycles(dst, 4); |
3035 case M68K_DIVS: | 3216 case M68K_DIVS: |
3036 case M68K_DIVU: | 3217 case M68K_DIVU: |
3037 { | 3218 { |
3038 //TODO: cycle exact division | 3219 //TODO: cycle exact division |
3039 dst = cycles(dst, inst->op == M68K_DIVS ? 158 : 140); | 3220 dst = cycles(dst, inst->op == M68K_DIVS ? 158 : 140); |
3040 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 3221 dst = set_flag(dst, 0, FLAG_C, opts); |
3041 dst = push_r(dst, RDX); | 3222 dst = push_r(dst, RDX); |
3042 dst = push_r(dst, RAX); | 3223 dst = push_r(dst, RAX); |
3043 if (dst_op.mode == MODE_REG_DIRECT) { | 3224 if (dst_op.mode == MODE_REG_DIRECT) { |
3044 dst = mov_rr(dst, dst_op.base, RAX, SZ_D); | 3225 dst = mov_rr(dst, dst_op.base, RAX, SZ_D); |
3045 } else { | 3226 } else { |
3102 dst = mov_rrdisp8(dst, RAX, dst_op.base, dst_op.disp, SZ_W); | 3283 dst = mov_rrdisp8(dst, RAX, dst_op.base, dst_op.disp, SZ_W); |
3103 } | 3284 } |
3104 dst = cmp_ir(dst, 0, RAX, SZ_W); | 3285 dst = cmp_ir(dst, 0, RAX, SZ_W); |
3105 dst = pop_r(dst, RAX); | 3286 dst = pop_r(dst, RAX); |
3106 dst = pop_r(dst, RDX); | 3287 dst = pop_r(dst, RDX); |
3107 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 3288 dst = set_flag(dst, 0, FLAG_V, opts); |
3108 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3289 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
3109 dst = setcc_r(dst, CC_S, FLAG_N); | 3290 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3110 end_off = dst+1; | 3291 end_off = dst+1; |
3111 dst = jmp(dst, dst+2); | 3292 dst = jmp(dst, dst+2); |
3112 *norm_off = dst - (norm_off + 1); | 3293 *norm_off = dst - (norm_off + 1); |
3113 if (inst->op == M68K_DIVS) { | 3294 if (inst->op == M68K_DIVS) { |
3114 *skip_sec_check = dst - (skip_sec_check+1); | 3295 *skip_sec_check = dst - (skip_sec_check+1); |
3115 } | 3296 } |
3116 dst = pop_r(dst, RAX); | 3297 dst = pop_r(dst, RAX); |
3117 dst = pop_r(dst, RDX); | 3298 dst = pop_r(dst, RDX); |
3118 dst = mov_ir(dst, 1, FLAG_V, SZ_B); | 3299 dst = set_flag(dst, 1, FLAG_V, opts); |
3119 *end_off = dst - (end_off + 1); | 3300 *end_off = dst - (end_off + 1); |
3120 break; | 3301 break; |
3121 } | 3302 } |
3122 case M68K_EOR: | 3303 case M68K_EOR: |
3123 dst = cycles(dst, BUS); | 3304 dst = cycles(dst, BUS); |
3134 dst = xor_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 3315 dst = xor_ir(dst, src_op.disp, dst_op.base, inst->extra.size); |
3135 } else { | 3316 } else { |
3136 dst = xor_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3317 dst = xor_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3137 } | 3318 } |
3138 } | 3319 } |
3139 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 3320 dst = set_flag(dst, 0, FLAG_C, opts); |
3140 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3321 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
3141 dst = setcc_r(dst, CC_S, FLAG_N); | 3322 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3142 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 3323 dst = set_flag(dst, 0, FLAG_V, opts); |
3143 dst = m68k_save_result(inst, dst, opts); | 3324 dst = m68k_save_result(inst, dst, opts); |
3144 break; | 3325 break; |
3145 case M68K_EORI_CCR: | 3326 case M68K_EORI_CCR: |
3146 case M68K_EORI_SR: | 3327 case M68K_EORI_SR: |
3147 dst = cycles(dst, 20); | 3328 dst = cycles(dst, 20); |
3148 //TODO: If ANDI to SR, trap if not in supervisor mode | 3329 //TODO: If ANDI to SR, trap if not in supervisor mode |
3149 if (inst->src.params.immed & 0x1) { | 3330 if (inst->src.params.immed & 0x1) { |
3150 dst = xor_ir(dst, 1, FLAG_C, SZ_B); | 3331 dst = xor_flag(dst, 1, FLAG_C, opts); |
3151 } | 3332 } |
3152 if (inst->src.params.immed & 0x2) { | 3333 if (inst->src.params.immed & 0x2) { |
3153 dst = xor_ir(dst, 1, FLAG_V, SZ_B); | 3334 dst = xor_flag(dst, 1, FLAG_V, opts); |
3154 } | 3335 } |
3155 if (inst->src.params.immed & 0x4) { | 3336 if (inst->src.params.immed & 0x4) { |
3156 dst = xor_ir(dst, 1, FLAG_Z, SZ_B); | 3337 dst = xor_flag(dst, 1, FLAG_Z, opts); |
3157 } | 3338 } |
3158 if (inst->src.params.immed & 0x8) { | 3339 if (inst->src.params.immed & 0x8) { |
3159 dst = xor_ir(dst, 1, FLAG_N, SZ_B); | 3340 dst = xor_flag(dst, 1, FLAG_N, opts); |
3160 } | 3341 } |
3161 if (inst->src.params.immed & 0x10) { | 3342 if (inst->src.params.immed & 0x10) { |
3162 dst = xor_irdisp8(dst, 1, CONTEXT, 0, SZ_B); | 3343 dst = xor_flag(dst, 1, FLAG_X, opts); |
3163 } | 3344 } |
3164 if (inst->op == M68K_ORI_SR) { | 3345 if (inst->op == M68K_ORI_SR) { |
3165 dst = xor_irdisp8(dst, inst->src.params.immed >> 8, CONTEXT, offsetof(m68k_context, status), SZ_B); | 3346 dst = xor_irdisp8(dst, inst->src.params.immed >> 8, CONTEXT, offsetof(m68k_context, status), SZ_B); |
3166 if (inst->src.params.immed & 0x700) { | 3347 if (inst->src.params.immed & 0x700) { |
3167 dst = call(dst, opts->do_sync); | 3348 dst = call(dst, opts->do_sync); |
3208 break; | 3389 break; |
3209 case M68K_MOVE_CCR: | 3390 case M68K_MOVE_CCR: |
3210 case M68K_MOVE_SR: | 3391 case M68K_MOVE_SR: |
3211 //TODO: Privilege check for MOVE to SR | 3392 //TODO: Privilege check for MOVE to SR |
3212 if (src_op.mode == MODE_IMMED) { | 3393 if (src_op.mode == MODE_IMMED) { |
3213 dst = mov_ir(dst, src_op.disp & 0x1, FLAG_C, SZ_B); | 3394 dst = set_flag(dst, src_op.disp & 0x1, FLAG_C, opts); |
3214 dst = mov_ir(dst, (src_op.disp >> 1) & 0x1, FLAG_V, SZ_B); | 3395 dst = set_flag(dst, (src_op.disp >> 1) & 0x1, FLAG_V, opts); |
3215 dst = mov_ir(dst, (src_op.disp >> 2) & 0x1, FLAG_Z, SZ_B); | 3396 dst = set_flag(dst, (src_op.disp >> 2) & 0x1, FLAG_Z, opts); |
3216 dst = mov_ir(dst, (src_op.disp >> 3) & 0x1, FLAG_N, SZ_B); | 3397 dst = set_flag(dst, (src_op.disp >> 3) & 0x1, FLAG_N, opts); |
3217 dst = mov_irind(dst, (src_op.disp >> 4) & 0x1, CONTEXT, SZ_B); | 3398 dst = set_flag(dst, (src_op.disp >> 4) & 0x1, FLAG_X, opts); |
3218 if (inst->op == M68K_MOVE_SR) { | 3399 if (inst->op == M68K_MOVE_SR) { |
3219 dst = mov_irdisp8(dst, (src_op.disp >> 8), CONTEXT, offsetof(m68k_context, status), SZ_B); | 3400 dst = mov_irdisp8(dst, (src_op.disp >> 8), CONTEXT, offsetof(m68k_context, status), SZ_B); |
3220 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { | 3401 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { |
3221 //leave supervisor mode | 3402 //leave supervisor mode |
3222 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); | 3403 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); |
3295 } | 3476 } |
3296 dst = imul_rr(dst, SCRATCH1, dst_reg, SZ_D); | 3477 dst = imul_rr(dst, SCRATCH1, dst_reg, SZ_D); |
3297 if (dst_op.mode == MODE_REG_DISPLACE8) { | 3478 if (dst_op.mode == MODE_REG_DISPLACE8) { |
3298 dst = mov_rrdisp8(dst, dst_reg, dst_op.base, dst_op.disp, SZ_D); | 3479 dst = mov_rrdisp8(dst, dst_reg, dst_op.base, dst_op.disp, SZ_D); |
3299 } | 3480 } |
3300 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 3481 dst = set_flag(dst, 0, FLAG_V, opts); |
3301 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 3482 dst = set_flag(dst, 0, FLAG_C, opts); |
3302 dst = cmp_ir(dst, 0, dst_reg, SZ_D); | 3483 dst = cmp_ir(dst, 0, dst_reg, SZ_D); |
3303 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3484 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
3304 dst = setcc_r(dst, CC_S, FLAG_N); | 3485 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3305 break; | 3486 break; |
3306 //case M68K_NBCD: | 3487 //case M68K_NBCD: |
3307 case M68K_NEG: | 3488 case M68K_NEG: |
3308 dst = cycles(dst, BUS); | 3489 dst = cycles(dst, BUS); |
3309 if (dst_op.mode == MODE_REG_DIRECT) { | 3490 if (dst_op.mode == MODE_REG_DIRECT) { |
3310 dst = neg_r(dst, dst_op.base, inst->extra.size); | 3491 dst = neg_r(dst, dst_op.base, inst->extra.size); |
3311 } else { | 3492 } else { |
3312 dst = neg_rdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); | 3493 dst = neg_rdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); |
3313 } | 3494 } |
3314 dst = setcc_r(dst, CC_C, FLAG_C); | 3495 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
3315 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3496 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
3316 dst = setcc_r(dst, CC_S, FLAG_N); | 3497 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3317 dst = setcc_r(dst, CC_O, FLAG_V); | 3498 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); |
3318 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 3499 if (opts->flag_regs[FLAG_C] >= 0) { |
3500 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | |
3501 } else { | |
3502 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | |
3503 } | |
3319 dst = m68k_save_result(inst, dst, opts); | 3504 dst = m68k_save_result(inst, dst, opts); |
3320 break; | 3505 break; |
3321 case M68K_NEGX: | 3506 case M68K_NEGX: { |
3322 dst = cycles(dst, BUS); | 3507 dst = cycles(dst, BUS); |
3323 if (dst_op.mode == MODE_REG_DIRECT) { | 3508 if (dst_op.mode == MODE_REG_DIRECT) { |
3324 if (dst_op.base == SCRATCH1) { | 3509 if (dst_op.base == SCRATCH1) { |
3325 dst = push_r(dst, SCRATCH2); | 3510 dst = push_r(dst, SCRATCH2); |
3326 dst = xor_rr(dst, SCRATCH2, SCRATCH2, inst->extra.size); | 3511 dst = xor_rr(dst, SCRATCH2, SCRATCH2, inst->extra.size); |
3327 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); | 3512 dst = flag_to_carry(dst, FLAG_X, opts); |
3328 dst = sbb_rr(dst, dst_op.base, SCRATCH2, inst->extra.size); | 3513 dst = sbb_rr(dst, dst_op.base, SCRATCH2, inst->extra.size); |
3329 dst = mov_rr(dst, SCRATCH2, dst_op.base, inst->extra.size); | 3514 dst = mov_rr(dst, SCRATCH2, dst_op.base, inst->extra.size); |
3330 dst = pop_r(dst, SCRATCH2); | 3515 dst = pop_r(dst, SCRATCH2); |
3331 } else { | 3516 } else { |
3332 dst = xor_rr(dst, SCRATCH1, SCRATCH1, inst->extra.size); | 3517 dst = xor_rr(dst, SCRATCH1, SCRATCH1, inst->extra.size); |
3333 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); | 3518 dst = flag_to_carry(dst, FLAG_X, opts); |
3334 dst = sbb_rr(dst, dst_op.base, SCRATCH1, inst->extra.size); | 3519 dst = sbb_rr(dst, dst_op.base, SCRATCH1, inst->extra.size); |
3335 dst = mov_rr(dst, SCRATCH1, dst_op.base, inst->extra.size); | 3520 dst = mov_rr(dst, SCRATCH1, dst_op.base, inst->extra.size); |
3336 } | 3521 } |
3337 } else { | 3522 } else { |
3338 dst = xor_rr(dst, SCRATCH1, SCRATCH1, inst->extra.size); | 3523 dst = xor_rr(dst, SCRATCH1, SCRATCH1, inst->extra.size); |
3339 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); | 3524 dst = flag_to_carry(dst, FLAG_X, opts); |
3340 dst = sbb_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, inst->extra.size); | 3525 dst = sbb_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, inst->extra.size); |
3341 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, inst->extra.size); | 3526 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, inst->extra.size); |
3342 } | 3527 } |
3343 dst = setcc_r(dst, CC_C, FLAG_C); | 3528 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
3344 dst = jcc(dst, CC_Z, dst+4); | 3529 uint8_t *after_flag_set = dst+1; |
3345 dst = mov_ir(dst, 0, FLAG_Z, SZ_B); | 3530 dst = jcc(dst, CC_Z, dst+2); |
3346 dst = setcc_r(dst, CC_S, FLAG_N); | 3531 dst = set_flag(dst, 0, FLAG_Z, opts); |
3347 dst = setcc_r(dst, CC_O, FLAG_V); | 3532 *after_flag_set = dst - (after_flag_set+1); |
3348 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 3533 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3534 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | |
3535 if (opts->flag_regs[FLAG_C] >= 0) { | |
3536 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | |
3537 } else { | |
3538 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | |
3539 } | |
3349 dst = m68k_save_result(inst, dst, opts); | 3540 dst = m68k_save_result(inst, dst, opts); |
3350 break; | 3541 break; |
3351 break; | 3542 } |
3352 case M68K_NOP: | 3543 case M68K_NOP: |
3353 dst = cycles(dst, BUS); | 3544 dst = cycles(dst, BUS); |
3354 break; | 3545 break; |
3355 case M68K_NOT: | 3546 case M68K_NOT: |
3356 if (dst_op.mode == MODE_REG_DIRECT) { | 3547 if (dst_op.mode == MODE_REG_DIRECT) { |
3359 } else { | 3550 } else { |
3360 dst = not_rdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); | 3551 dst = not_rdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); |
3361 dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); | 3552 dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); |
3362 } | 3553 } |
3363 | 3554 |
3364 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 3555 dst = set_flag(dst, 0, FLAG_C, opts); |
3365 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3556 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
3366 dst = setcc_r(dst, CC_S, FLAG_N); | 3557 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3367 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 3558 dst = set_flag(dst, 0, FLAG_V, opts); |
3368 dst = m68k_save_result(inst, dst, opts); | 3559 dst = m68k_save_result(inst, dst, opts); |
3369 break; | 3560 break; |
3370 case M68K_OR: | 3561 case M68K_OR: |
3371 dst = cycles(dst, BUS); | 3562 dst = cycles(dst, BUS); |
3372 if (src_op.mode == MODE_REG_DIRECT) { | 3563 if (src_op.mode == MODE_REG_DIRECT) { |
3382 dst = or_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 3573 dst = or_ir(dst, src_op.disp, dst_op.base, inst->extra.size); |
3383 } else { | 3574 } else { |
3384 dst = or_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3575 dst = or_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3385 } | 3576 } |
3386 } | 3577 } |
3387 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 3578 dst = set_flag(dst, 0, FLAG_C, opts); |
3388 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3579 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
3389 dst = setcc_r(dst, CC_S, FLAG_N); | 3580 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3390 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 3581 dst = set_flag(dst, 0, FLAG_V, opts); |
3391 dst = m68k_save_result(inst, dst, opts); | 3582 dst = m68k_save_result(inst, dst, opts); |
3392 break; | 3583 break; |
3393 case M68K_ORI_CCR: | 3584 case M68K_ORI_CCR: |
3394 case M68K_ORI_SR: | 3585 case M68K_ORI_SR: |
3395 dst = cycles(dst, 20); | 3586 dst = cycles(dst, 20); |
3396 //TODO: If ANDI to SR, trap if not in supervisor mode | 3587 //TODO: If ANDI to SR, trap if not in supervisor mode |
3397 if (inst->src.params.immed & 0x1) { | 3588 if (inst->src.params.immed & 0x1) { |
3398 dst = mov_ir(dst, 1, FLAG_C, SZ_B); | 3589 dst = set_flag(dst, 1, FLAG_C, opts); |
3399 } | 3590 } |
3400 if (inst->src.params.immed & 0x2) { | 3591 if (inst->src.params.immed & 0x2) { |
3401 dst = mov_ir(dst, 1, FLAG_V, SZ_B); | 3592 dst = set_flag(dst, 1, FLAG_V, opts); |
3402 } | 3593 } |
3403 if (inst->src.params.immed & 0x4) { | 3594 if (inst->src.params.immed & 0x4) { |
3404 dst = mov_ir(dst, 1, FLAG_Z, SZ_B); | 3595 dst = set_flag(dst, 1, FLAG_Z, opts); |
3405 } | 3596 } |
3406 if (inst->src.params.immed & 0x8) { | 3597 if (inst->src.params.immed & 0x8) { |
3407 dst = mov_ir(dst, 1, FLAG_N, SZ_B); | 3598 dst = set_flag(dst, 1, FLAG_N, opts); |
3408 } | 3599 } |
3409 if (inst->src.params.immed & 0x10) { | 3600 if (inst->src.params.immed & 0x10) { |
3410 dst = mov_irind(dst, 1, CONTEXT, SZ_B); | 3601 dst = set_flag(dst, 1, FLAG_X, opts); |
3411 } | 3602 } |
3412 if (inst->op == M68K_ORI_SR) { | 3603 if (inst->op == M68K_ORI_SR) { |
3413 dst = or_irdisp8(dst, inst->src.params.immed >> 8, CONTEXT, offsetof(m68k_context, status), SZ_B); | 3604 dst = or_irdisp8(dst, inst->src.params.immed >> 8, CONTEXT, offsetof(m68k_context, status), SZ_B); |
3414 if (inst->src.params.immed & 0x700) { | 3605 if (inst->src.params.immed & 0x700) { |
3415 dst = call(dst, opts->do_sync); | 3606 dst = call(dst, opts->do_sync); |
3421 dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); | 3612 dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); |
3422 dst = call(dst, (uint8_t *)print_regs_exit); | 3613 dst = call(dst, (uint8_t *)print_regs_exit); |
3423 break; | 3614 break; |
3424 case M68K_ROL: | 3615 case M68K_ROL: |
3425 case M68K_ROR: | 3616 case M68K_ROR: |
3426 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 3617 dst = set_flag(dst, 0, FLAG_V, opts); |
3427 if (inst->src.addr_mode == MODE_UNUSED) { | 3618 if (inst->src.addr_mode == MODE_UNUSED) { |
3428 dst = cycles(dst, BUS); | 3619 dst = cycles(dst, BUS); |
3429 //Memory rotate | 3620 //Memory rotate |
3430 if (inst->op == M68K_ROL) { | 3621 if (inst->op == M68K_ROL) { |
3431 dst = rol_ir(dst, 1, dst_op.base, inst->extra.size); | 3622 dst = rol_ir(dst, 1, dst_op.base, inst->extra.size); |
3432 } else { | 3623 } else { |
3433 dst = ror_ir(dst, 1, dst_op.base, inst->extra.size); | 3624 dst = ror_ir(dst, 1, dst_op.base, inst->extra.size); |
3434 } | 3625 } |
3435 dst = setcc_r(dst, CC_C, FLAG_C); | 3626 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
3436 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); | 3627 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); |
3437 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3628 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
3438 dst = setcc_r(dst, CC_S, FLAG_N); | 3629 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3439 dst = m68k_save_result(inst, dst, opts); | 3630 dst = m68k_save_result(inst, dst, opts); |
3440 } else { | 3631 } else { |
3441 if (src_op.mode == MODE_IMMED) { | 3632 if (src_op.mode == MODE_IMMED) { |
3442 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2); | 3633 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2); |
3443 if (dst_op.mode == MODE_REG_DIRECT) { | 3634 if (dst_op.mode == MODE_REG_DIRECT) { |
3451 dst = rol_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3642 dst = rol_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3452 } else { | 3643 } else { |
3453 dst = ror_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3644 dst = ror_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3454 } | 3645 } |
3455 } | 3646 } |
3456 dst = setcc_r(dst, CC_C, FLAG_C); | 3647 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
3457 } else { | 3648 } else { |
3458 if (src_op.mode == MODE_REG_DIRECT) { | 3649 if (src_op.mode == MODE_REG_DIRECT) { |
3459 if (src_op.base != SCRATCH1) { | 3650 if (src_op.base != SCRATCH1) { |
3460 dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_B); | 3651 dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_B); |
3461 } | 3652 } |
3500 dst = rol_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); | 3691 dst = rol_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); |
3501 } else { | 3692 } else { |
3502 dst = ror_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); | 3693 dst = ror_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); |
3503 } | 3694 } |
3504 } | 3695 } |
3505 dst = setcc_r(dst, CC_C, FLAG_C); | 3696 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
3506 end_off = dst + 1; | 3697 end_off = dst + 1; |
3507 dst = jmp(dst, dst+2); | 3698 dst = jmp(dst, dst+2); |
3508 *zero_off = dst - (zero_off+1); | 3699 *zero_off = dst - (zero_off+1); |
3509 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 3700 dst = set_flag(dst, 0, FLAG_C, opts); |
3510 *end_off = dst - (end_off+1); | 3701 *end_off = dst - (end_off+1); |
3511 } | 3702 } |
3512 if (dst_op.mode == MODE_REG_DIRECT) { | 3703 if (dst_op.mode == MODE_REG_DIRECT) { |
3513 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); | 3704 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); |
3514 } else { | 3705 } else { |
3515 dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); | 3706 dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); |
3516 } | 3707 } |
3517 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3708 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
3518 dst = setcc_r(dst, CC_S, FLAG_N); | 3709 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3519 } | 3710 } |
3520 break; | 3711 break; |
3521 case M68K_ROXL: | 3712 case M68K_ROXL: |
3522 case M68K_ROXR: | 3713 case M68K_ROXR: |
3523 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 3714 dst = set_flag(dst, 0, FLAG_V, opts); |
3524 if (inst->src.addr_mode == MODE_UNUSED) { | 3715 if (inst->src.addr_mode == MODE_UNUSED) { |
3525 dst = cycles(dst, BUS); | 3716 dst = cycles(dst, BUS); |
3526 //Memory rotate | 3717 //Memory rotate |
3527 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); | 3718 dst = flag_to_carry(dst, FLAG_X, opts); |
3528 if (inst->op == M68K_ROXL) { | 3719 if (inst->op == M68K_ROXL) { |
3529 dst = rcl_ir(dst, 1, dst_op.base, inst->extra.size); | 3720 dst = rcl_ir(dst, 1, dst_op.base, inst->extra.size); |
3530 } else { | 3721 } else { |
3531 dst = rcr_ir(dst, 1, dst_op.base, inst->extra.size); | 3722 dst = rcr_ir(dst, 1, dst_op.base, inst->extra.size); |
3532 } | 3723 } |
3533 dst = setcc_r(dst, CC_C, FLAG_C); | 3724 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
3725 if (opts->flag_regs[FLAG_C] < 0) { | |
3726 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | |
3727 } | |
3534 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); | 3728 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); |
3535 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3729 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
3536 dst = setcc_r(dst, CC_S, FLAG_N); | 3730 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3537 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 3731 if (opts->flag_regs[FLAG_C] >= 0) { |
3732 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | |
3733 } | |
3538 dst = m68k_save_result(inst, dst, opts); | 3734 dst = m68k_save_result(inst, dst, opts); |
3539 } else { | 3735 } else { |
3540 if (src_op.mode == MODE_IMMED) { | 3736 if (src_op.mode == MODE_IMMED) { |
3541 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2); | 3737 dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2); |
3542 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); | 3738 dst = flag_to_carry(dst, FLAG_X, opts); |
3543 if (dst_op.mode == MODE_REG_DIRECT) { | 3739 if (dst_op.mode == MODE_REG_DIRECT) { |
3544 if (inst->op == M68K_ROXL) { | 3740 if (inst->op == M68K_ROXL) { |
3545 dst = rcl_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 3741 dst = rcl_ir(dst, src_op.disp, dst_op.base, inst->extra.size); |
3546 } else { | 3742 } else { |
3547 dst = rcr_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 3743 dst = rcr_ir(dst, src_op.disp, dst_op.base, inst->extra.size); |
3551 dst = rcl_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3747 dst = rcl_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3552 } else { | 3748 } else { |
3553 dst = rcr_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3749 dst = rcr_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3554 } | 3750 } |
3555 } | 3751 } |
3556 dst = setcc_r(dst, CC_C, FLAG_C); | 3752 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
3557 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 3753 if (opts->flag_regs[FLAG_C] >= 0) { |
3754 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | |
3755 } else { | |
3756 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | |
3757 } | |
3558 } else { | 3758 } else { |
3559 if (src_op.mode == MODE_REG_DIRECT) { | 3759 if (src_op.mode == MODE_REG_DIRECT) { |
3560 if (src_op.base != SCRATCH1) { | 3760 if (src_op.base != SCRATCH1) { |
3561 dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_B); | 3761 dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_B); |
3562 } | 3762 } |
3569 dst = add_rr(dst, SCRATCH1, CYCLES, SZ_D); | 3769 dst = add_rr(dst, SCRATCH1, CYCLES, SZ_D); |
3570 dst = add_rr(dst, SCRATCH1, CYCLES, SZ_D); | 3770 dst = add_rr(dst, SCRATCH1, CYCLES, SZ_D); |
3571 dst = cmp_ir(dst, 32, SCRATCH1, SZ_B); | 3771 dst = cmp_ir(dst, 32, SCRATCH1, SZ_B); |
3572 norm_off = dst+1; | 3772 norm_off = dst+1; |
3573 dst = jcc(dst, CC_L, dst+2); | 3773 dst = jcc(dst, CC_L, dst+2); |
3574 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); | 3774 dst = flag_to_carry(dst, FLAG_X, opts); |
3575 if (dst_op.mode == MODE_REG_DIRECT) { | 3775 if (dst_op.mode == MODE_REG_DIRECT) { |
3576 if (inst->op == M68K_ROXL) { | 3776 if (inst->op == M68K_ROXL) { |
3577 dst = rcl_ir(dst, 31, dst_op.base, inst->extra.size); | 3777 dst = rcl_ir(dst, 31, dst_op.base, inst->extra.size); |
3578 dst = rcl_ir(dst, 1, dst_op.base, inst->extra.size); | 3778 dst = rcl_ir(dst, 1, dst_op.base, inst->extra.size); |
3579 } else { | 3779 } else { |
3587 } else { | 3787 } else { |
3588 dst = rcr_irdisp8(dst, 31, dst_op.base, dst_op.disp, inst->extra.size); | 3788 dst = rcr_irdisp8(dst, 31, dst_op.base, dst_op.disp, inst->extra.size); |
3589 dst = rcr_irdisp8(dst, 1, dst_op.base, dst_op.disp, inst->extra.size); | 3789 dst = rcr_irdisp8(dst, 1, dst_op.base, dst_op.disp, inst->extra.size); |
3590 } | 3790 } |
3591 } | 3791 } |
3592 dst = setcc_rind(dst, CC_C, CONTEXT); | 3792 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); |
3593 dst = sub_ir(dst, 32, SCRATCH1, SZ_B); | 3793 dst = sub_ir(dst, 32, SCRATCH1, SZ_B); |
3594 *norm_off = dst - (norm_off+1); | 3794 *norm_off = dst - (norm_off+1); |
3595 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); | 3795 dst = flag_to_carry(dst, FLAG_X, opts); |
3596 if (dst_op.mode == MODE_REG_DIRECT) { | 3796 if (dst_op.mode == MODE_REG_DIRECT) { |
3597 if (inst->op == M68K_ROXL) { | 3797 if (inst->op == M68K_ROXL) { |
3598 dst = rcl_clr(dst, dst_op.base, inst->extra.size); | 3798 dst = rcl_clr(dst, dst_op.base, inst->extra.size); |
3599 } else { | 3799 } else { |
3600 dst = rcr_clr(dst, dst_op.base, inst->extra.size); | 3800 dst = rcr_clr(dst, dst_op.base, inst->extra.size); |
3604 dst = rcl_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); | 3804 dst = rcl_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); |
3605 } else { | 3805 } else { |
3606 dst = rcr_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); | 3806 dst = rcr_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size); |
3607 } | 3807 } |
3608 } | 3808 } |
3609 dst = setcc_r(dst, CC_C, FLAG_C); | 3809 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
3610 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 3810 if (opts->flag_regs[FLAG_C] >= 0) { |
3811 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | |
3812 } else { | |
3813 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | |
3814 } | |
3611 end_off = dst + 1; | 3815 end_off = dst + 1; |
3612 dst = jmp(dst, dst+2); | 3816 dst = jmp(dst, dst+2); |
3613 *zero_off = dst - (zero_off+1); | 3817 *zero_off = dst - (zero_off+1); |
3614 //Carry flag is set to X flag when count is 0, this is different from ROR/ROL | 3818 //Carry flag is set to X flag when count is 0, this is different from ROR/ROL |
3615 dst = mov_rindr(dst, CONTEXT, FLAG_C, SZ_B); | 3819 dst = flag_to_flag(dst, FLAG_X, FLAG_C, opts); |
3616 *end_off = dst - (end_off+1); | 3820 *end_off = dst - (end_off+1); |
3617 } | 3821 } |
3618 if (dst_op.mode == MODE_REG_DIRECT) { | 3822 if (dst_op.mode == MODE_REG_DIRECT) { |
3619 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); | 3823 dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); |
3620 } else { | 3824 } else { |
3621 dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); | 3825 dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); |
3622 } | 3826 } |
3623 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3827 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
3624 dst = setcc_r(dst, CC_S, FLAG_N); | 3828 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3625 } | 3829 } |
3626 break; | 3830 break; |
3627 case M68K_RTE: | 3831 case M68K_RTE: |
3628 //TODO: Trap if not in system mode | 3832 //TODO: Trap if not in system mode |
3629 //Read saved SR | 3833 //Read saved SR |
3659 dst = add_ir(dst, 4, opts->aregs[7], SZ_D); | 3863 dst = add_ir(dst, 4, opts->aregs[7], SZ_D); |
3660 //Get native address and jump to it | 3864 //Get native address and jump to it |
3661 dst = call(dst, opts->native_addr); | 3865 dst = call(dst, opts->native_addr); |
3662 dst = jmp_r(dst, SCRATCH1); | 3866 dst = jmp_r(dst, SCRATCH1); |
3663 break; | 3867 break; |
3664 case M68K_SBCD: | 3868 case M68K_SBCD: { |
3665 if (src_op.base != SCRATCH2) { | 3869 if (src_op.base != SCRATCH2) { |
3666 if (src_op.mode == MODE_REG_DIRECT) { | 3870 if (src_op.mode == MODE_REG_DIRECT) { |
3667 dst = mov_rr(dst, src_op.base, SCRATCH2, SZ_B); | 3871 dst = mov_rr(dst, src_op.base, SCRATCH2, SZ_B); |
3668 } else { | 3872 } else { |
3669 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_B); | 3873 dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_B); |
3674 dst = mov_rr(dst, dst_op.base, SCRATCH1, SZ_B); | 3878 dst = mov_rr(dst, dst_op.base, SCRATCH1, SZ_B); |
3675 } else { | 3879 } else { |
3676 dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, SZ_B); | 3880 dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, SZ_B); |
3677 } | 3881 } |
3678 } | 3882 } |
3679 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); | 3883 dst = flag_to_carry(dst, FLAG_X, opts); |
3680 dst = jcc(dst, CC_NC, dst+5); | 3884 dst = jcc(dst, CC_NC, dst+5); |
3681 dst = sub_ir(dst, 1, SCRATCH1, SZ_B); | 3885 dst = sub_ir(dst, 1, SCRATCH1, SZ_B); |
3682 dst = call(dst, (uint8_t *)bcd_sub); | 3886 dst = call(dst, (uint8_t *)bcd_sub); |
3683 dst = mov_rr(dst, CH, FLAG_C, SZ_B); | 3887 dst = reg_to_flag(dst, CH, FLAG_C, opts); |
3684 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 3888 dst = reg_to_flag(dst, CH, FLAG_X, opts); |
3685 dst = cmp_ir(dst, 0, SCRATCH1, SZ_B); | 3889 dst = cmp_ir(dst, 0, SCRATCH1, SZ_B); |
3686 dst = jcc(dst, CC_Z, dst+4); | 3890 uint8_t *after_flag_set = dst+1; |
3687 dst = mov_ir(dst, 0, FLAG_Z, SZ_B); | 3891 dst = jcc(dst, CC_Z, dst+2); |
3892 dst = set_flag(dst, 0, FLAG_Z, opts); | |
3893 *after_flag_set = dst - (after_flag_set+1); | |
3688 if (dst_op.base != SCRATCH1) { | 3894 if (dst_op.base != SCRATCH1) { |
3689 if (dst_op.mode == MODE_REG_DIRECT) { | 3895 if (dst_op.mode == MODE_REG_DIRECT) { |
3690 dst = mov_rr(dst, SCRATCH1, dst_op.base, SZ_B); | 3896 dst = mov_rr(dst, SCRATCH1, dst_op.base, SZ_B); |
3691 } else { | 3897 } else { |
3692 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_B); | 3898 dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_B); |
3693 } | 3899 } |
3694 } | 3900 } |
3695 dst = m68k_save_result(inst, dst, opts); | 3901 dst = m68k_save_result(inst, dst, opts); |
3696 break; | 3902 break; |
3903 } | |
3697 case M68K_STOP: { | 3904 case M68K_STOP: { |
3698 //TODO: Trap if not in system mode | 3905 //TODO: Trap if not in system mode |
3699 //manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction | 3906 //manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction |
3700 //possibly even 12 since that's how long MOVE to SR takes | 3907 //possibly even 12 since that's how long MOVE to SR takes |
3701 dst = cycles(dst, BUS*2); | 3908 dst = cycles(dst, BUS*2); |
3702 dst = mov_ir(dst, src_op.disp & 0x1, FLAG_C, SZ_B); | 3909 dst = set_flag(dst, src_op.disp & 0x1, FLAG_C, opts); |
3703 dst = mov_ir(dst, (src_op.disp >> 1) & 0x1, FLAG_V, SZ_B); | 3910 dst = set_flag(dst, (src_op.disp >> 1) & 0x1, FLAG_V, opts); |
3704 dst = mov_ir(dst, (src_op.disp >> 2) & 0x1, FLAG_Z, SZ_B); | 3911 dst = set_flag(dst, (src_op.disp >> 2) & 0x1, FLAG_Z, opts); |
3705 dst = mov_ir(dst, (src_op.disp >> 3) & 0x1, FLAG_N, SZ_B); | 3912 dst = set_flag(dst, (src_op.disp >> 3) & 0x1, FLAG_N, opts); |
3706 dst = mov_irind(dst, (src_op.disp >> 4) & 0x1, CONTEXT, SZ_B); | 3913 dst = set_flag(dst, (src_op.disp >> 4) & 0x1, FLAG_X, opts); |
3707 dst = mov_irdisp8(dst, (src_op.disp >> 8), CONTEXT, offsetof(m68k_context, status), SZ_B); | 3914 dst = mov_irdisp8(dst, (src_op.disp >> 8), CONTEXT, offsetof(m68k_context, status), SZ_B); |
3708 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { | 3915 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { |
3709 //leave supervisor mode | 3916 //leave supervisor mode |
3710 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); | 3917 dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D); |
3711 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); | 3918 dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D); |
3743 } else { | 3950 } else { |
3744 dst = sub_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, size); | 3951 dst = sub_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, size); |
3745 } | 3952 } |
3746 } | 3953 } |
3747 if (inst->dst.addr_mode != MODE_AREG) { | 3954 if (inst->dst.addr_mode != MODE_AREG) { |
3748 dst = setcc_r(dst, CC_C, FLAG_C); | 3955 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
3749 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3956 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
3750 dst = setcc_r(dst, CC_S, FLAG_N); | 3957 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3751 dst = setcc_r(dst, CC_O, FLAG_V); | 3958 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); |
3752 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 3959 if (opts->flag_regs[FLAG_C] >= 0) { |
3960 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | |
3961 } else { | |
3962 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); | |
3963 } | |
3753 } | 3964 } |
3754 dst = m68k_save_result(inst, dst, opts); | 3965 dst = m68k_save_result(inst, dst, opts); |
3755 break; | 3966 break; |
3756 case M68K_SUBX: | 3967 case M68K_SUBX: { |
3757 dst = cycles(dst, BUS); | 3968 dst = cycles(dst, BUS); |
3758 dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B); | 3969 dst = flag_to_carry(dst, FLAG_X, opts); |
3759 if (src_op.mode == MODE_REG_DIRECT) { | 3970 if (src_op.mode == MODE_REG_DIRECT) { |
3760 if (dst_op.mode == MODE_REG_DIRECT) { | 3971 if (dst_op.mode == MODE_REG_DIRECT) { |
3761 dst = sbb_rr(dst, src_op.base, dst_op.base, inst->extra.size); | 3972 dst = sbb_rr(dst, src_op.base, dst_op.base, inst->extra.size); |
3762 } else { | 3973 } else { |
3763 dst = sbb_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); | 3974 dst = sbb_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); |
3769 dst = sbb_ir(dst, src_op.disp, dst_op.base, inst->extra.size); | 3980 dst = sbb_ir(dst, src_op.disp, dst_op.base, inst->extra.size); |
3770 } else { | 3981 } else { |
3771 dst = sbb_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 3982 dst = sbb_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
3772 } | 3983 } |
3773 } | 3984 } |
3774 dst = setcc_r(dst, CC_C, FLAG_C); | 3985 dst = set_flag_cond(dst, CC_C, FLAG_C, opts); |
3775 dst = jcc(dst, CC_Z, dst+4); | 3986 if (opts->flag_regs[FLAG_C] < 0) { |
3776 dst = mov_ir(dst, 0, FLAG_Z, SZ_B); | 3987 dst = set_flag_cond(dst, CC_C, FLAG_X, opts); |
3777 dst = setcc_r(dst, CC_S, FLAG_N); | 3988 } |
3778 dst = setcc_r(dst, CC_O, FLAG_V); | 3989 uint8_t *after_flag_set = dst+1; |
3779 dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B); | 3990 dst = jcc(dst, CC_Z, dst+2); |
3991 dst = set_flag(dst, 0, FLAG_Z, opts); | |
3992 *after_flag_set = dst - (after_flag_set+1); | |
3993 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); | |
3994 dst = set_flag_cond(dst, CC_O, FLAG_V, opts); | |
3995 if (opts->flag_regs[FLAG_C] >= 0) { | |
3996 dst = flag_to_flag(dst, FLAG_C, FLAG_X, opts); | |
3997 } | |
3780 dst = m68k_save_result(inst, dst, opts); | 3998 dst = m68k_save_result(inst, dst, opts); |
3781 break; | 3999 break; |
4000 } | |
3782 case M68K_SWAP: | 4001 case M68K_SWAP: |
3783 dst = cycles(dst, BUS); | 4002 dst = cycles(dst, BUS); |
3784 if (src_op.mode == MODE_REG_DIRECT) { | 4003 if (src_op.mode == MODE_REG_DIRECT) { |
3785 dst = rol_ir(dst, 16, src_op.base, SZ_D); | 4004 dst = rol_ir(dst, 16, src_op.base, SZ_D); |
3786 dst = cmp_ir(dst, 0, src_op.base, SZ_D); | 4005 dst = cmp_ir(dst, 0, src_op.base, SZ_D); |
3787 } else{ | 4006 } else{ |
3788 dst = rol_irdisp8(dst, 16, src_op.base, src_op.disp, SZ_D); | 4007 dst = rol_irdisp8(dst, 16, src_op.base, src_op.disp, SZ_D); |
3789 dst = cmp_irdisp8(dst, 0, src_op.base, src_op.disp, SZ_D); | 4008 dst = cmp_irdisp8(dst, 0, src_op.base, src_op.disp, SZ_D); |
3790 } | 4009 } |
3791 | 4010 |
3792 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 4011 dst = set_flag(dst, 0, FLAG_C, opts); |
3793 dst = setcc_r(dst, CC_Z, FLAG_Z); | 4012 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
3794 dst = setcc_r(dst, CC_S, FLAG_N); | 4013 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3795 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 4014 dst = set_flag(dst, 0, FLAG_V, opts); |
3796 break; | 4015 break; |
3797 //case M68K_TAS: | 4016 //case M68K_TAS: |
3798 case M68K_TRAP: | 4017 case M68K_TRAP: |
3799 dst = mov_ir(dst, src_op.disp + VECTOR_TRAP_0, SCRATCH2, SZ_D); | 4018 dst = mov_ir(dst, src_op.disp + VECTOR_TRAP_0, SCRATCH2, SZ_D); |
3800 dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D); | 4019 dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D); |
3806 if (src_op.mode == MODE_REG_DIRECT) { | 4025 if (src_op.mode == MODE_REG_DIRECT) { |
3807 dst = cmp_ir(dst, 0, src_op.base, inst->extra.size); | 4026 dst = cmp_ir(dst, 0, src_op.base, inst->extra.size); |
3808 } else { //M68000 doesn't support immedate operand for tst, so this must be MODE_REG_DISPLACE8 | 4027 } else { //M68000 doesn't support immedate operand for tst, so this must be MODE_REG_DISPLACE8 |
3809 dst = cmp_irdisp8(dst, 0, src_op.base, src_op.disp, inst->extra.size); | 4028 dst = cmp_irdisp8(dst, 0, src_op.base, src_op.disp, inst->extra.size); |
3810 } | 4029 } |
3811 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 4030 dst = set_flag(dst, 0, FLAG_C, opts); |
3812 dst = setcc_r(dst, CC_Z, FLAG_Z); | 4031 dst = set_flag_cond(dst, CC_Z, FLAG_Z, opts); |
3813 dst = setcc_r(dst, CC_S, FLAG_N); | 4032 dst = set_flag_cond(dst, CC_S, FLAG_N, opts); |
3814 dst = mov_ir(dst, 0, FLAG_V, SZ_B); | 4033 dst = set_flag(dst, 0, FLAG_V, opts); |
3815 break; | 4034 break; |
3816 case M68K_UNLK: | 4035 case M68K_UNLK: |
3817 dst = cycles(dst, BUS); | 4036 dst = cycles(dst, BUS); |
3818 if (dst_op.mode == MODE_REG_DIRECT) { | 4037 if (dst_op.mode == MODE_REG_DIRECT) { |
3819 dst = mov_rr(dst, dst_op.base, opts->aregs[7], SZ_D); | 4038 dst = mov_rr(dst, dst_op.base, opts->aregs[7], SZ_D); |