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