comparison m68k_core_x86.c @ 612:5a6ff0d76032

Removed bcd_add and bcd_sub from runtime.S and generated the logic inline with the rest of abcd and sbcd translation. Fixed some edge cases and undefined flag behavior in the process
author Michael Pavone <pavone@retrodev.com>
date Sun, 28 Dec 2014 17:25:36 -0800
parents 744b305965f7
children 9d6fed6501ba
comparison
equal deleted inserted replaced
611:744b305965f7 612:5a6ff0d76032
1402 mov_rr(code, dst_op->base, opts->gen.scratch1, SZ_B); 1402 mov_rr(code, dst_op->base, opts->gen.scratch1, SZ_B);
1403 } else { 1403 } else {
1404 mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch1, SZ_B); 1404 mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch1, SZ_B);
1405 } 1405 }
1406 } 1406 }
1407 uint8_t other_reg;
1408 //WARNING: This may need adjustment if register assignments change
1409 if (opts->gen.scratch2 > RBX) {
1410 other_reg = RAX;
1411 xchg_rr(code, opts->gen.scratch2, RAX, SZ_D);
1412 } else {
1413 other_reg = opts->gen.scratch2;
1414 }
1415 mov_rr(code, opts->gen.scratch1, opts->gen.scratch1 + (AH-RAX), SZ_B);
1416 mov_rr(code, other_reg, other_reg + (AH-RAX), SZ_B);
1417 and_ir(code, 0xF0, opts->gen.scratch1, SZ_B);
1418 and_ir(code, 0xF0, other_reg, SZ_B);
1419 and_ir(code, 0xF, opts->gen.scratch1 + (AH-RAX), SZ_B);
1420 and_ir(code, 0xF, other_reg + (AH-RAX), SZ_B);
1421 //do op on low nibble
1407 flag_to_carry(opts, FLAG_X); 1422 flag_to_carry(opts, FLAG_X);
1408 jcc(code, CC_NC, code->cur + 5);
1409 if (inst->op == M68K_ABCD) { 1423 if (inst->op == M68K_ABCD) {
1410 add_ir(code, 1, opts->gen.scratch1, SZ_B); 1424 adc_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B);
1411 } else { 1425 } else {
1412 sub_ir(code, 1, opts->gen.scratch1, SZ_B); 1426 sbb_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B);
1413 } 1427 }
1414 call(code, (code_ptr) (inst->op == M68K_ABCD ? bcd_add : bcd_sub)); 1428 cmp_ir(code, 0xA, opts->gen.scratch1 + (AH-RAX), SZ_B);
1415 reg_to_flag(opts, CH, FLAG_C); 1429 code_ptr no_adjust = code->cur+1;
1416 reg_to_flag(opts, CH, FLAG_X); 1430 //add correction factor if necessary
1431 jcc(code, CC_B, no_adjust);
1432 if (inst->op == M68K_ABCD) {
1433 add_ir(code, 6, opts->gen.scratch1 + (AH-RAX), SZ_B);
1434 } else {
1435 sub_ir(code, 6, opts->gen.scratch1 + (AH-RAX), SZ_B);
1436 }
1437 *no_adjust = code->cur - (no_adjust+1);
1438 //add low nibble result to one of the high nibble operands
1439 add_rr(code, opts->gen.scratch1 + (AH-RAX), opts->gen.scratch1, SZ_B);
1440 if (inst->op == M68K_ABCD) {
1441 add_rr(code, other_reg, opts->gen.scratch1, SZ_B);
1442 } else {
1443 sub_rr(code, other_reg, opts->gen.scratch1, SZ_B);
1444 }
1445 if (opts->gen.scratch2 > RBX) {
1446 mov_rr(code, opts->gen.scratch2, RAX, SZ_D);
1447 }
1448 set_flag(opts, 0, FLAG_C);
1449 set_flag(opts, 0, FLAG_V);
1450 code_ptr def_adjust = code->cur+1;
1451 jcc(code, CC_C, def_adjust);
1452 cmp_ir(code, 0xA0, opts->gen.scratch1, SZ_B);
1453 no_adjust = code->cur+1;
1454 jcc(code, CC_B, no_adjust);
1455 *def_adjust = code->cur - (def_adjust + 1);
1456 set_flag(opts, 1, FLAG_C);
1457 if (inst->op == M68K_ABCD) {
1458 add_ir(code, 0x60, opts->gen.scratch1, SZ_B);
1459 } else {
1460 sub_ir(code, 0x60, opts->gen.scratch1, SZ_B);
1461 }
1462 //V flag is set based on the result of the addition of the
1463 //result and the correction factor
1464 set_flag_cond(opts, CC_O, FLAG_V);
1465 *no_adjust = code->cur - (no_adjust+1);
1466 flag_to_flag(opts, FLAG_C, FLAG_X);
1467
1417 cmp_ir(code, 0, opts->gen.scratch1, SZ_B); 1468 cmp_ir(code, 0, opts->gen.scratch1, SZ_B);
1469 set_flag_cond(opts, CC_S, FLAG_N);
1418 jcc(code, CC_Z, code->cur + 4); 1470 jcc(code, CC_Z, code->cur + 4);
1419 set_flag(opts, 0, FLAG_Z); 1471 set_flag(opts, 0, FLAG_Z);
1420 if (dst_op->base != opts->gen.scratch1) { 1472 if (dst_op->base != opts->gen.scratch1) {
1421 if (dst_op->mode == MODE_REG_DIRECT) { 1473 if (dst_op->mode == MODE_REG_DIRECT) {
1422 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_B); 1474 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_B);