comparison m68k_core_x86.c @ 833:841e44c5af83

Fix for abcd/sbcd. Hopefully got it 100% right this time.
author Michael Pavone <pavone@retrodev.com>
date Mon, 19 Oct 2015 19:16:57 -0700
parents 724bbec47f86
children 65f9041b5f17
comparison
equal deleted inserted replaced
832:0433fdd9ba66 833:841e44c5af83
1395 } else { 1395 } else {
1396 other_reg = opts->gen.scratch2; 1396 other_reg = opts->gen.scratch2;
1397 } 1397 }
1398 mov_rr(code, opts->gen.scratch1, opts->gen.scratch1 + (AH-RAX), SZ_B); 1398 mov_rr(code, opts->gen.scratch1, opts->gen.scratch1 + (AH-RAX), SZ_B);
1399 mov_rr(code, other_reg, other_reg + (AH-RAX), SZ_B); 1399 mov_rr(code, other_reg, other_reg + (AH-RAX), SZ_B);
1400 and_ir(code, 0xF0, opts->gen.scratch1, SZ_B);
1401 and_ir(code, 0xF0, other_reg, SZ_B);
1402 and_ir(code, 0xF, opts->gen.scratch1 + (AH-RAX), SZ_B); 1400 and_ir(code, 0xF, opts->gen.scratch1 + (AH-RAX), SZ_B);
1403 and_ir(code, 0xF, other_reg + (AH-RAX), SZ_B); 1401 and_ir(code, 0xF, other_reg + (AH-RAX), SZ_B);
1404 //do op on low nibble 1402 //do op on low nibble so we can determine if an adjustment is necessary
1405 flag_to_carry(opts, FLAG_X); 1403 flag_to_carry(opts, FLAG_X);
1406 if (inst->op == M68K_ABCD) { 1404 if (inst->op == M68K_ABCD) {
1407 adc_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B); 1405 adc_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B);
1408 } else { 1406 } else {
1409 sbb_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B); 1407 sbb_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B);
1410 } 1408 }
1411 cmp_ir(code, 0xA, opts->gen.scratch1 + (AH-RAX), SZ_B); 1409 cmp_ir(code, 0xA, opts->gen.scratch1 + (AH-RAX), SZ_B);
1410 mov_ir(code, 0xA0, other_reg + (AH-RAX), SZ_B);
1412 code_ptr no_adjust = code->cur+1; 1411 code_ptr no_adjust = code->cur+1;
1413 //add correction factor if necessary 1412 //add correction factor if necessary
1414 jcc(code, CC_B, no_adjust); 1413 jcc(code, CC_B, no_adjust);
1414 mov_ir(code, 6, opts->gen.scratch1 + (AH-RAX), SZ_B);
1415 mov_ir(code, inst->op == M68K_ABCD ? 0x9A : 0xA6, other_reg + (AH-RAX), SZ_B);
1416 code_ptr after_adjust = code->cur+1;
1417 jmp(code, after_adjust);
1418
1419 *no_adjust = code->cur - (no_adjust+1);
1420 xor_rr(code, opts->gen.scratch1 + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B);
1421 *after_adjust = code->cur - (after_adjust+1);
1422
1423 //do op on full byte
1424 flag_to_carry(opts, FLAG_X);
1415 if (inst->op == M68K_ABCD) { 1425 if (inst->op == M68K_ABCD) {
1416 add_ir(code, 6, opts->gen.scratch1 + (AH-RAX), SZ_B); 1426 adc_rr(code, other_reg, opts->gen.scratch1, SZ_B);
1417 } else { 1427 } else {
1418 sub_ir(code, 6, opts->gen.scratch1 + (AH-RAX), SZ_B); 1428 sbb_rr(code, other_reg, opts->gen.scratch1, SZ_B);
1419 }
1420 *no_adjust = code->cur - (no_adjust+1);
1421 //add low nibble result to one of the high nibble operands
1422 add_rr(code, opts->gen.scratch1 + (AH-RAX), opts->gen.scratch1, SZ_B);
1423 if (inst->op == M68K_ABCD) {
1424 add_rr(code, other_reg, opts->gen.scratch1, SZ_B);
1425 } else {
1426 sub_rr(code, other_reg, opts->gen.scratch1, SZ_B);
1427 }
1428 if (opts->gen.scratch2 > RBX) {
1429 mov_rr(code, opts->gen.scratch2, RAX, SZ_D);
1430 } 1429 }
1431 set_flag(opts, 0, FLAG_C); 1430 set_flag(opts, 0, FLAG_C);
1432 set_flag(opts, 0, FLAG_V); 1431 //determine if we need a correction on the upper nibble
1433 code_ptr def_adjust = code->cur+1; 1432 code_ptr def_adjust = code->cur+1;
1434 jcc(code, CC_C, def_adjust); 1433 jcc(code, CC_C, def_adjust);
1435 cmp_ir(code, 0xA0, opts->gen.scratch1, SZ_B); 1434 cmp_rr(code, other_reg + (AH-RAX), opts->gen.scratch1, SZ_B);
1436 no_adjust = code->cur+1; 1435 no_adjust = code->cur+1;
1437 jcc(code, CC_B, no_adjust); 1436 jcc(code, CC_B, no_adjust);
1438 *def_adjust = code->cur - (def_adjust + 1); 1437 *def_adjust = code->cur - (def_adjust + 1);
1439 set_flag(opts, 1, FLAG_C); 1438 set_flag(opts, 1, FLAG_C);
1439 or_ir(code, 0x60, opts->gen.scratch1 + (AH-RAX), SZ_B);
1440 *no_adjust = code->cur - (no_adjust+1);
1440 if (inst->op == M68K_ABCD) { 1441 if (inst->op == M68K_ABCD) {
1441 add_ir(code, 0x60, opts->gen.scratch1, SZ_B); 1442 add_rr(code, opts->gen.scratch1 + (AH-RAX), opts->gen.scratch1, SZ_B);
1442 } else { 1443 } else {
1443 sub_ir(code, 0x60, opts->gen.scratch1, SZ_B); 1444 sub_rr(code, opts->gen.scratch1 + (AH-RAX), opts->gen.scratch1, SZ_B);
1444 } 1445 }
1445 //V flag is set based on the result of the addition of the 1446 code_ptr no_ensure_carry = code->cur+1;
1447 jcc(code, CC_NC, no_ensure_carry);
1448 set_flag(opts, 1, FLAG_C);
1449 *no_ensure_carry = code->cur - (no_ensure_carry+1);
1450 //restore RAX if necessary
1451 if (opts->gen.scratch2 > RBX) {
1452 mov_rr(code, opts->gen.scratch2, RAX, SZ_D);
1453 }
1454 //V flag is set based on the result of the addition/subtraction of the
1446 //result and the correction factor 1455 //result and the correction factor
1447 set_flag_cond(opts, CC_O, FLAG_V); 1456 set_flag_cond(opts, CC_O, FLAG_V);
1448 *no_adjust = code->cur - (no_adjust+1); 1457
1449 flag_to_flag(opts, FLAG_C, FLAG_X); 1458 flag_to_flag(opts, FLAG_C, FLAG_X);
1450 1459
1451 cmp_ir(code, 0, opts->gen.scratch1, SZ_B); 1460 cmp_ir(code, 0, opts->gen.scratch1, SZ_B);
1452 set_flag_cond(opts, CC_S, FLAG_N); 1461 set_flag_cond(opts, CC_S, FLAG_N);
1453 code_ptr no_setz = code->cur+1; 1462 code_ptr no_setz = code->cur+1;
2483 shl_ir(code, 2, opts->gen.scratch1, SZ_D); 2492 shl_ir(code, 2, opts->gen.scratch1, SZ_D);
2484 call(code, opts->read_32); 2493 call(code, opts->read_32);
2485 call(code, opts->native_addr_and_sync); 2494 call(code, opts->native_addr_and_sync);
2486 cycles(&opts->gen, 18); 2495 cycles(&opts->gen, 18);
2487 jmp_r(code, opts->gen.scratch1); 2496 jmp_r(code, opts->gen.scratch1);
2488 2497
2489 opts->odd_address = code->cur; 2498 opts->odd_address = code->cur;
2490 mov_ir(code, (int64_t)stderr, RDI, SZ_PTR); 2499 mov_ir(code, (int64_t)stderr, RDI, SZ_PTR);
2491 mov_ir(code, (int64_t)"Attempt to execute code at odd address\n", RSI, SZ_PTR); 2500 mov_ir(code, (int64_t)"Attempt to execute code at odd address\n", RSI, SZ_PTR);
2492 call_args_abi(code, (code_ptr)fprintf, 2, RDI, RSI, RDX); 2501 call_args_abi(code, (code_ptr)fprintf, 2, RDI, RSI, RDX);
2493 xor_rr(code, RDI, RDI, SZ_D); 2502 xor_rr(code, RDI, RDI, SZ_D);