Mercurial > repos > blastem
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); |