Mercurial > repos > blastem
comparison m68k_to_x86.c @ 228:1ed81ef2a3a2
Fix overflow detection in divs. Fix negative immediate source for divs
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 21 Apr 2013 16:44:46 -0700 |
parents | 28a6697e847b |
children | d9bf8e61c33c |
comparison
equal
deleted
inserted
replaced
227:42123feab62d | 228:1ed81ef2a3a2 |
---|---|
3124 dst = cycles(dst, 4); | 3124 dst = cycles(dst, 4); |
3125 break; | 3125 break; |
3126 } | 3126 } |
3127 case M68K_DIVS: | 3127 case M68K_DIVS: |
3128 case M68K_DIVU: | 3128 case M68K_DIVU: |
3129 //TODO: Trap on division by zero | 3129 { |
3130 //TODO: cycle exact division | |
3130 dst = cycles(dst, inst->op == M68K_DIVS ? 158 : 140); | 3131 dst = cycles(dst, inst->op == M68K_DIVS ? 158 : 140); |
3132 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | |
3131 dst = push_r(dst, RDX); | 3133 dst = push_r(dst, RDX); |
3132 dst = push_r(dst, RAX); | 3134 dst = push_r(dst, RAX); |
3133 if (dst_op.mode == MODE_REG_DIRECT) { | 3135 if (dst_op.mode == MODE_REG_DIRECT) { |
3134 dst = mov_rr(dst, dst_op.base, RAX, SZ_D); | 3136 dst = mov_rr(dst, dst_op.base, RAX, SZ_D); |
3135 } else { | 3137 } else { |
3136 dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, RAX, SZ_D); | 3138 dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, RAX, SZ_D); |
3137 } | 3139 } |
3138 if (src_op.mode == MODE_IMMED) { | 3140 if (src_op.mode == MODE_IMMED) { |
3139 dst = mov_ir(dst, src_op.disp, SCRATCH2, SZ_D); | 3141 dst = mov_ir(dst, (src_op.disp & 0x8000) && inst->op == M68K_DIVS ? src_op.disp | 0xFFFF0000 : src_op.disp, SCRATCH2, SZ_D); |
3140 } else if (src_op.mode == MODE_REG_DIRECT) { | 3142 } else if (src_op.mode == MODE_REG_DIRECT) { |
3141 if (inst->op == M68K_DIVS) { | 3143 if (inst->op == M68K_DIVS) { |
3142 dst = movsx_rr(dst, src_op.base, SCRATCH2, SZ_W, SZ_D); | 3144 dst = movsx_rr(dst, src_op.base, SCRATCH2, SZ_W, SZ_D); |
3143 } else { | 3145 } else { |
3144 dst = movzx_rr(dst, src_op.base, SCRATCH2, SZ_W, SZ_D); | 3146 dst = movzx_rr(dst, src_op.base, SCRATCH2, SZ_W, SZ_D); |
3148 dst = movsx_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_W, SZ_D); | 3150 dst = movsx_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_W, SZ_D); |
3149 } else { | 3151 } else { |
3150 dst = movzx_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_W, SZ_D); | 3152 dst = movzx_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_W, SZ_D); |
3151 } | 3153 } |
3152 } | 3154 } |
3155 dst = cmp_ir(dst, 0, SCRATCH2, SZ_D); | |
3156 uint8_t * not_zero = dst+1; | |
3157 dst = jcc(dst, CC_NZ, dst+2); | |
3158 dst = pop_r(dst, RAX); | |
3159 dst = pop_r(dst, RDX); | |
3160 dst = mov_ir(dst, VECTOR_INT_DIV_ZERO, SCRATCH2, SZ_D); | |
3161 dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D); | |
3162 dst = jmp(dst, (uint8_t *)m68k_trap); | |
3163 *not_zero = dst - (not_zero+1); | |
3153 if (inst->op == M68K_DIVS) { | 3164 if (inst->op == M68K_DIVS) { |
3154 dst = cdq(dst); | 3165 dst = cdq(dst); |
3155 } else { | 3166 } else { |
3156 dst = xor_rr(dst, RDX, RDX, SZ_D); | 3167 dst = xor_rr(dst, RDX, RDX, SZ_D); |
3157 } | 3168 } |
3158 if (inst->op == M68K_DIVS) { | 3169 if (inst->op == M68K_DIVS) { |
3159 dst = idiv_r(dst, SCRATCH2, SZ_D); | 3170 dst = idiv_r(dst, SCRATCH2, SZ_D); |
3160 } else { | 3171 } else { |
3161 dst = div_r(dst, SCRATCH2, SZ_D); | 3172 dst = div_r(dst, SCRATCH2, SZ_D); |
3162 } | 3173 } |
3163 dst = cmp_ir(dst, 0x10000, RAX, SZ_D); | 3174 uint8_t * skip_sec_check; |
3164 if (inst->op == M68K_DIVS) { | 3175 if (inst->op == M68K_DIVS) { |
3165 uint8_t * skip_sec_check = dst + 1; | 3176 dst = cmp_ir(dst, 0x8000, RAX, SZ_D); |
3166 dst = jcc(dst, CC_C, dst+2); | 3177 skip_sec_check = dst + 1; |
3167 dst = cmp_ir(dst, -0x10000, RAX, SZ_D); | 3178 dst = jcc(dst, CC_GE, dst+2); |
3179 dst = cmp_ir(dst, -0x8000, RAX, SZ_D); | |
3168 norm_off = dst+1; | 3180 norm_off = dst+1; |
3169 dst = jcc(dst, CC_LE, dst+2); | 3181 dst = jcc(dst, CC_L, dst+2); |
3170 *skip_sec_check = dst - (skip_sec_check+1); | 3182 } else { |
3171 } else { | 3183 dst = cmp_ir(dst, 0x10000, RAX, SZ_D); |
3172 norm_off = dst+1; | 3184 norm_off = dst+1; |
3173 dst = jcc(dst, CC_NC, dst+2); | 3185 dst = jcc(dst, CC_NC, dst+2); |
3174 } | 3186 } |
3175 if (dst_op.mode == MODE_REG_DIRECT) { | 3187 if (dst_op.mode == MODE_REG_DIRECT) { |
3176 dst = mov_rr(dst, RDX, dst_op.base, SZ_W); | 3188 dst = mov_rr(dst, RDX, dst_op.base, SZ_W); |
3188 dst = setcc_r(dst, CC_Z, FLAG_Z); | 3200 dst = setcc_r(dst, CC_Z, FLAG_Z); |
3189 dst = setcc_r(dst, CC_S, FLAG_N); | 3201 dst = setcc_r(dst, CC_S, FLAG_N); |
3190 end_off = dst+1; | 3202 end_off = dst+1; |
3191 dst = jmp(dst, dst+2); | 3203 dst = jmp(dst, dst+2); |
3192 *norm_off = dst - (norm_off + 1); | 3204 *norm_off = dst - (norm_off + 1); |
3205 if (inst->op == M68K_DIVS) { | |
3206 *skip_sec_check = dst - (skip_sec_check+1); | |
3207 } | |
3193 dst = pop_r(dst, RAX); | 3208 dst = pop_r(dst, RAX); |
3194 dst = pop_r(dst, RDX); | 3209 dst = pop_r(dst, RDX); |
3195 dst = mov_ir(dst, 1, FLAG_V, SZ_B); | 3210 dst = mov_ir(dst, 1, FLAG_V, SZ_B); |
3196 *end_off = dst - (end_off + 1); | 3211 *end_off = dst - (end_off + 1); |
3197 dst = mov_ir(dst, 0, FLAG_C, SZ_B); | 3212 break; |
3198 break; | 3213 } |
3199 case M68K_EOR: | 3214 case M68K_EOR: |
3200 dst = cycles(dst, BUS); | 3215 dst = cycles(dst, BUS); |
3201 if (src_op.mode == MODE_REG_DIRECT) { | 3216 if (src_op.mode == MODE_REG_DIRECT) { |
3202 if (dst_op.mode == MODE_REG_DIRECT) { | 3217 if (dst_op.mode == MODE_REG_DIRECT) { |
3203 dst = xor_rr(dst, src_op.base, dst_op.base, inst->extra.size); | 3218 dst = xor_rr(dst, src_op.base, dst_op.base, inst->extra.size); |