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