Mercurial > repos > blastem
comparison z80_to_x86.c @ 1045:e0489abfdab0
Implement half-carry for INC, DEC and NEG
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 26 Jul 2016 00:11:33 -0700 |
parents | 1625555e346e |
children | a27fdf43f1a7 |
comparison
equal
deleted
inserted
replaced
1044:1625555e346e | 1045:e0489abfdab0 |
---|---|
200 if (size == SZ_B) { | 200 if (size == SZ_B) { |
201 call(code, opts->read_8); | 201 call(code, opts->read_8); |
202 } else { | 202 } else { |
203 call(code, opts->read_16); | 203 call(code, opts->read_16); |
204 } | 204 } |
205 if (modify) { | |
206 //pop_r(code, opts->gen.scratch2); | |
207 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W); | |
208 } | |
209 } | 205 } |
210 ea->base = opts->gen.scratch1; | 206 ea->base = opts->gen.scratch1; |
211 break; | 207 break; |
212 case Z80_IMMED: | 208 case Z80_IMMED: |
213 ea->mode = MODE_IMMED; | 209 ea->mode = MODE_IMMED; |
223 if (size == SZ_B) { | 219 if (size == SZ_B) { |
224 call(code, opts->read_8); | 220 call(code, opts->read_8); |
225 } else { | 221 } else { |
226 call(code, opts->read_16); | 222 call(code, opts->read_16); |
227 } | 223 } |
228 if (modify) { | |
229 //pop_r(code, opts->gen.scratch2); | |
230 mov_ir(code, inst->immed, opts->gen.scratch2, SZ_W); | |
231 } | |
232 } | 224 } |
233 ea->base = opts->gen.scratch1; | 225 ea->base = opts->gen.scratch1; |
234 break; | 226 break; |
235 case Z80_IX_DISPLACE: | 227 case Z80_IX_DISPLACE: |
236 case Z80_IY_DISPLACE: | 228 case Z80_IY_DISPLACE: |
245 if (size == SZ_B) { | 237 if (size == SZ_B) { |
246 call(code, opts->read_8); | 238 call(code, opts->read_8); |
247 } else { | 239 } else { |
248 call(code, opts->read_16); | 240 call(code, opts->read_16); |
249 } | 241 } |
250 if (modify) { | |
251 //pop_r(code, opts->gen.scratch2); | |
252 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W); | |
253 } | |
254 } | 242 } |
255 ea->base = opts->gen.scratch1; | 243 ea->base = opts->gen.scratch1; |
256 break; | 244 break; |
257 case Z80_UNUSED: | 245 case Z80_UNUSED: |
258 ea->mode = MODE_UNUSED; | 246 ea->mode = MODE_UNUSED; |
291 { | 279 { |
292 case Z80_REG_INDIRECT: | 280 case Z80_REG_INDIRECT: |
293 case Z80_IMMED_INDIRECT: | 281 case Z80_IMMED_INDIRECT: |
294 case Z80_IX_DISPLACE: | 282 case Z80_IX_DISPLACE: |
295 case Z80_IY_DISPLACE: | 283 case Z80_IY_DISPLACE: |
284 if (inst->op != Z80_LD) { | |
285 mov_rdispr(&opts->gen.code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W); | |
286 } | |
296 if (z80_size(inst) == SZ_B) { | 287 if (z80_size(inst) == SZ_B) { |
297 call(&opts->gen.code, opts->write_8); | 288 call(&opts->gen.code, opts->write_8); |
298 } else { | 289 } else { |
299 call(&opts->gen.code, opts->write_16_lowfirst); | 290 call(&opts->gen.code, opts->write_16_lowfirst); |
300 } | 291 } |
1041 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | 1032 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); |
1042 z80_save_reg(inst, opts); | 1033 z80_save_reg(inst, opts); |
1043 z80_save_ea(code, inst, opts); | 1034 z80_save_ea(code, inst, opts); |
1044 break; | 1035 break; |
1045 case Z80_INC: | 1036 case Z80_INC: |
1037 case Z80_DEC: | |
1046 if(z80_size(inst) == SZ_W) { | 1038 if(z80_size(inst) == SZ_W) { |
1047 num_cycles += 2; | 1039 num_cycles += 2; |
1048 } | 1040 } |
1049 cycles(&opts->gen, num_cycles); | 1041 cycles(&opts->gen, num_cycles); |
1050 translate_z80_reg(inst, &dst_op, opts); | 1042 translate_z80_reg(inst, &dst_op, opts); |
1051 if (dst_op.mode == MODE_UNUSED) { | 1043 if (dst_op.mode == MODE_UNUSED) { |
1052 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); | 1044 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); |
1053 } | 1045 } |
1054 if (dst_op.mode == MODE_REG_DIRECT) { | |
1055 add_ir(code, 1, dst_op.base, z80_size(inst)); | |
1056 } else { | |
1057 add_irdisp(code, 1, dst_op.base, dst_op.disp, z80_size(inst)); | |
1058 } | |
1059 if (z80_size(inst) == SZ_B) { | 1046 if (z80_size(inst) == SZ_B) { |
1060 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1047 if (dst_op.mode == MODE_REG_DIRECT) { |
1061 //TODO: Implement half-carry flag | 1048 if (dst_op.base >= AH && dst_op.base <= BH) { |
1049 mov_rr(code, dst_op.base - AH, opts->gen.scratch2, SZ_W); | |
1050 } else { | |
1051 mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_B); | |
1052 } | |
1053 } else { | |
1054 mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_B); | |
1055 } | |
1056 } | |
1057 if (inst->op == Z80_INC) { | |
1058 if (dst_op.mode == MODE_REG_DIRECT) { | |
1059 add_ir(code, 1, dst_op.base, z80_size(inst)); | |
1060 } else { | |
1061 add_irdisp(code, 1, dst_op.base, dst_op.disp, z80_size(inst)); | |
1062 } | |
1063 } else { | |
1064 if (dst_op.mode == MODE_REG_DIRECT) { | |
1065 sub_ir(code, 1, dst_op.base, z80_size(inst)); | |
1066 } else { | |
1067 sub_irdisp(code, 1, dst_op.base, dst_op.disp, z80_size(inst)); | |
1068 } | |
1069 } | |
1070 if (z80_size(inst) == SZ_B) { | |
1071 mov_irdisp(code, inst->op == Z80_DEC, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | |
1062 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); | 1072 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); |
1063 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | 1073 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); |
1064 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | 1074 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); |
1065 } | 1075 int bit = 4; |
1066 z80_save_reg(inst, opts); | 1076 if (dst_op.mode == MODE_REG_DIRECT) { |
1067 z80_save_ea(code, inst, opts); | 1077 if (dst_op.base >= AH && dst_op.base <= BH) { |
1068 z80_save_result(opts, inst); | 1078 bit = 12; |
1069 break; | 1079 xor_rr(code, dst_op.base - AH, opts->gen.scratch2, SZ_W); |
1070 case Z80_DEC: | 1080 } else { |
1071 if(z80_size(inst) == SZ_W) { | 1081 xor_rr(code, dst_op.base, opts->gen.scratch2, SZ_B); |
1072 num_cycles += 2; | 1082 } |
1073 } | 1083 } else { |
1074 cycles(&opts->gen, num_cycles); | 1084 xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_B); |
1075 translate_z80_reg(inst, &dst_op, opts); | 1085 } |
1076 if (dst_op.mode == MODE_UNUSED) { | 1086 bt_ir(code, bit, opts->gen.scratch2, SZ_W); |
1077 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); | 1087 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); |
1078 } | |
1079 if (dst_op.mode == MODE_REG_DIRECT) { | |
1080 sub_ir(code, 1, dst_op.base, z80_size(inst)); | |
1081 } else { | |
1082 sub_irdisp(code, 1, dst_op.base, dst_op.disp, z80_size(inst)); | |
1083 } | |
1084 | |
1085 if (z80_size(inst) == SZ_B) { | |
1086 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | |
1087 //TODO: Implement half-carry flag | |
1088 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); | |
1089 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | |
1090 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | |
1091 } | 1088 } |
1092 z80_save_reg(inst, opts); | 1089 z80_save_reg(inst, opts); |
1093 z80_save_ea(code, inst, opts); | 1090 z80_save_ea(code, inst, opts); |
1094 z80_save_result(opts, inst); | 1091 z80_save_result(opts, inst); |
1095 break; | 1092 break; |
1105 | 1102 |
1106 code_ptr no_corf_low = code->cur+1; | 1103 code_ptr no_corf_low = code->cur+1; |
1107 jcc(code, CC_C, code->cur+2); | 1104 jcc(code, CC_C, code->cur+2); |
1108 *corf_low = code->cur - (corf_low + 1); | 1105 *corf_low = code->cur - (corf_low + 1); |
1109 mov_ir(code, 6, opts->gen.scratch2, SZ_B); | 1106 mov_ir(code, 6, opts->gen.scratch2, SZ_B); |
1110 //TODO: Deal with edge case of 9 in high nibble | |
1111 mov_ir(code, 0x90, opts->gen.scratch1, SZ_B); | 1107 mov_ir(code, 0x90, opts->gen.scratch1, SZ_B); |
1112 code_ptr after_cmp_set = code->cur+1; | 1108 code_ptr after_cmp_set = code->cur+1; |
1113 jmp(code, code->cur+2); | 1109 jmp(code, code->cur+2); |
1114 | 1110 |
1115 *no_corf_low = code->cur - (no_corf_low + 1); | 1111 *no_corf_low = code->cur - (no_corf_low + 1); |
1146 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B); | 1142 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1147 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1143 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1148 break; | 1144 break; |
1149 case Z80_NEG: | 1145 case Z80_NEG: |
1150 cycles(&opts->gen, num_cycles); | 1146 cycles(&opts->gen, num_cycles); |
1147 mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B); | |
1151 neg_r(code, opts->regs[Z80_A], SZ_B); | 1148 neg_r(code, opts->regs[Z80_A], SZ_B); |
1152 //TODO: Implement half-carry flag | |
1153 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | 1149 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); |
1154 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | 1150 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); |
1155 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 1151 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
1156 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); | 1152 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); |
1157 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1153 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1154 xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B); | |
1155 bt_ir(code, 4, opts->gen.scratch2, SZ_B); | |
1156 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); | |
1158 break; | 1157 break; |
1159 case Z80_CCF: | 1158 case Z80_CCF: |
1160 cycles(&opts->gen, num_cycles); | 1159 cycles(&opts->gen, num_cycles); |
1161 mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_C), opts->gen.scratch1, SZ_B); | 1160 mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_C), opts->gen.scratch1, SZ_B); |
1162 xor_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); | 1161 xor_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); |