comparison m68k_core_x86.c @ 577:0f367276a80c

Refactor a bunch of the arithmetic instructions in the 68K core to reduce duplicate code
author Michael Pavone <pavone@retrodev.com>
date Tue, 04 Mar 2014 22:12:43 -0800
parents a6f2db4df70d
children ec1365fb2954
comparison
equal deleted inserted replaced
576:a6f2db4df70d 577:0f367276a80c
508 } 508 }
509 509
510 void m68k_save_result(m68kinst * inst, m68k_options * opts) 510 void m68k_save_result(m68kinst * inst, m68k_options * opts)
511 { 511 {
512 code_info *code = &opts->gen.code; 512 code_info *code = &opts->gen.code;
513 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG) { 513 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_UNUSED) {
514 if (inst->dst.addr_mode == MODE_AREG_PREDEC && inst->src.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) { 514 if (inst->dst.addr_mode == MODE_AREG_PREDEC && inst->src.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) {
515 areg_to_native(opts, inst->dst.params.regs.pri, opts->gen.scratch2); 515 areg_to_native(opts, inst->dst.params.regs.pri, opts->gen.scratch2);
516 } 516 }
517 switch (inst->extra.size) 517 switch (inst->extra.size)
518 { 518 {
1327 if (inst->src.addr_mode == MODE_UNUSED) { 1327 if (inst->src.addr_mode == MODE_UNUSED) {
1328 m68k_save_result(inst, opts); 1328 m68k_save_result(inst, opts);
1329 } 1329 }
1330 } 1330 }
1331 1331
1332 void op_ir(code_info *code, m68kinst *inst, int32_t val, uint8_t dst, uint8_t size)
1333 {
1334 switch (inst->op)
1335 {
1336 case M68K_ADD: add_ir(code, val, dst, size); break;
1337 case M68K_ADDX: adc_ir(code, val, dst, size); break;
1338 case M68K_AND: and_ir(code, val, dst, size); break;
1339 case M68K_EOR: xor_ir(code, val, dst, size); break;
1340 case M68K_OR: or_ir(code, val, dst, size); break;
1341 case M68K_ROL: rol_ir(code, val, dst, size); break;
1342 case M68K_ROR: ror_ir(code, val, dst, size); break;
1343 case M68K_ROXL: rcl_ir(code, val, dst, size); break;
1344 case M68K_ROXR: rcr_ir(code, val, dst, size); break;
1345 case M68K_SUB: sub_ir(code, val, dst, size); break;
1346 case M68K_SUBX: sbb_ir(code, val, dst, size); break;
1347 }
1348 }
1349
1350 void op_irdisp(code_info *code, m68kinst *inst, int32_t val, uint8_t dst, int32_t disp, uint8_t size)
1351 {
1352 switch (inst->op)
1353 {
1354 case M68K_ADD: add_irdisp(code, val, dst, disp, size); break;
1355 case M68K_ADDX: adc_irdisp(code, val, dst, disp, size); break;
1356 case M68K_AND: and_irdisp(code, val, dst, disp, size); break;
1357 case M68K_EOR: xor_irdisp(code, val, dst, disp, size); break;
1358 case M68K_OR: or_irdisp(code, val, dst, disp, size); break;
1359 case M68K_ROL: rol_irdisp(code, val, dst, disp, size); break;
1360 case M68K_ROR: ror_irdisp(code, val, dst, disp, size); break;
1361 case M68K_ROXL: rcl_irdisp(code, val, dst, disp, size); break;
1362 case M68K_ROXR: rcr_irdisp(code, val, dst, disp, size); break;
1363 case M68K_SUB: sub_irdisp(code, val, dst, disp, size); break;
1364 case M68K_SUBX: sbb_irdisp(code, val, dst, disp, size); break;
1365 }
1366 }
1367
1368 void op_rr(code_info *code, m68kinst *inst, uint8_t src, uint8_t dst, uint8_t size)
1369 {
1370 switch (inst->op)
1371 {
1372 case M68K_ADD: add_rr(code, src, dst, size); break;
1373 case M68K_ADDX: adc_rr(code, src, dst, size); break;
1374 case M68K_AND: and_rr(code, src, dst, size); break;
1375 case M68K_EOR: xor_rr(code, src, dst, size); break;
1376 case M68K_OR: or_rr(code, src, dst, size); break;
1377 case M68K_SUB: sub_rr(code, src, dst, size); break;
1378 case M68K_SUBX: sbb_rr(code, src, dst, size); break;
1379 }
1380 }
1381
1382 void op_rrdisp(code_info *code, m68kinst *inst, uint8_t src, uint8_t dst, int32_t disp, uint8_t size)
1383 {
1384 switch (inst->op)
1385 {
1386 case M68K_ADD: add_rrdisp(code, src, dst, disp, size); break;
1387 case M68K_ADDX: adc_rrdisp(code, src, dst, disp, size); break;
1388 case M68K_AND: and_rrdisp(code, src, dst, disp, size); break;
1389 case M68K_EOR: xor_rrdisp(code, src, dst, disp, size); break;
1390 case M68K_OR: or_rrdisp(code, src, dst, disp, size); break;
1391 case M68K_SUB: sub_rrdisp(code, src, dst, disp, size); break;
1392 case M68K_SUBX: sbb_rrdisp(code, src, dst, disp, size); break;
1393 }
1394 }
1395
1396 void op_rdispr(code_info *code, m68kinst *inst, uint8_t src, int32_t disp, uint8_t dst, uint8_t size)
1397 {
1398 switch (inst->op)
1399 {
1400 case M68K_ADD: add_rdispr(code, src, disp, dst, size); break;
1401 case M68K_ADDX: adc_rdispr(code, src, disp, dst, size); break;
1402 case M68K_AND: and_rdispr(code, src, disp, dst, size); break;
1403 case M68K_EOR: xor_rdispr(code, src, disp, dst, size); break;
1404 case M68K_OR: or_rdispr(code, src, disp, dst, size); break;
1405 case M68K_SUB: sub_rdispr(code, src, disp, dst, size); break;
1406 case M68K_SUBX: sbb_rdispr(code, src, disp, dst, size); break;
1407 }
1408 }
1409
1410 void translate_m68k_arith(m68k_options *opts, m68kinst * inst, uint32_t flag_mask, x86_ea *src_op, x86_ea *dst_op)
1411 {
1412 code_info *code = &opts->gen.code;
1413 cycles(&opts->gen, BUS);
1414 if (inst->op == M68K_ADDX || inst->op == M68K_SUBX) {
1415 flag_to_carry(opts, FLAG_X);
1416 }
1417 uint8_t size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size;
1418 if (src_op->mode == MODE_REG_DIRECT) {
1419 if (dst_op->mode == MODE_REG_DIRECT) {
1420 op_rr(code, inst, src_op->base, dst_op->base, size);
1421 } else {
1422 op_rrdisp(code, inst, src_op->base, dst_op->base, dst_op->disp, size);
1423 }
1424 } else if (src_op->mode == MODE_REG_DISPLACE8) {
1425 op_rdispr(code, inst, src_op->base, src_op->disp, dst_op->base, size);
1426 } else {
1427 if (dst_op->mode == MODE_REG_DIRECT) {
1428 op_ir(code, inst, src_op->disp, dst_op->base, size);
1429 } else {
1430 op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, size);
1431 }
1432 }
1433 if (inst->dst.addr_mode != MODE_AREG) {
1434 update_flags(opts, flag_mask);
1435 if (inst->op == M68K_ADDX || inst->op == M68K_SUBX) {
1436 check_alloc_code(code, 2*MAX_INST_LEN);
1437 code_ptr after_flag_set = code->cur + 1;
1438 jcc(code, CC_Z, code->cur + 2);
1439 set_flag(opts, 0, FLAG_Z);
1440 *after_flag_set = code->cur - (after_flag_set+1);
1441 }
1442 }
1443 m68k_save_result(inst, opts);
1444 }
1445
1446 void op_r(code_info *code, m68kinst *inst, uint8_t dst, uint8_t size)
1447 {
1448 switch(inst->op)
1449 {
1450 case M68K_NEG: neg_r(code, dst, size); break;
1451 case M68K_NOT: not_r(code, dst, size); cmp_ir(code, 0, dst, size); break;
1452 case M68K_ROL: rol_clr(code, dst, size); break;
1453 case M68K_ROR: ror_clr(code, dst, size); break;
1454 case M68K_ROXL: rcl_clr(code, dst, size); break;
1455 case M68K_ROXR: rcr_clr(code, dst, size); break;
1456 case M68K_TST: cmp_ir(code, 0, dst, size); break;
1457 }
1458 }
1459
1460 void op_rdisp(code_info *code, m68kinst *inst, uint8_t dst, int32_t disp, uint8_t size)
1461 {
1462 switch(inst->op)
1463 {
1464 case M68K_NEG: neg_rdisp(code, dst, disp, size); break;
1465 case M68K_NOT: not_rdisp(code, dst, disp, size); cmp_irdisp(code, 0, dst, disp, size); break;
1466 case M68K_ROL: rol_clrdisp(code, dst, disp, size); break;
1467 case M68K_ROR: ror_clrdisp(code, dst, disp, size); break;
1468 case M68K_ROXL: rcl_clrdisp(code, dst, disp, size); break;
1469 case M68K_ROXR: rcr_clrdisp(code, dst, disp, size); break;
1470 case M68K_TST: cmp_irdisp(code, 0, dst, disp, size); break;
1471 }
1472 }
1473
1474 void translate_m68k_unary(m68k_options *opts, m68kinst *inst, uint32_t flag_mask, x86_ea *dst_op)
1475 {
1476 code_info *code = &opts->gen.code;
1477 cycles(&opts->gen, BUS);
1478 if (dst_op->mode == MODE_REG_DIRECT) {
1479 op_r(code, inst, dst_op->base, inst->extra.size);
1480 } else {
1481 op_rdisp(code, inst, dst_op->base, dst_op->disp, inst->extra.size);
1482 }
1483 update_flags(opts, flag_mask);
1484 m68k_save_result(inst, opts);
1485 }
1486
1332 #define BIT_SUPERVISOR 5 1487 #define BIT_SUPERVISOR 5
1333 1488
1334 void translate_m68k(m68k_options * opts, m68kinst * inst) 1489 void translate_m68k(m68k_options * opts, m68kinst * inst)
1335 { 1490 {
1336 code_ptr end_off, zero_off, norm_off; 1491 code_ptr end_off, zero_off, norm_off;
1420 } 1575 }
1421 } 1576 }
1422 m68k_save_result(inst, opts); 1577 m68k_save_result(inst, opts);
1423 break; 1578 break;
1424 case M68K_ADD: 1579 case M68K_ADD:
1425 cycles(&opts->gen, BUS); 1580 case M68K_SUB:
1426 size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size; 1581 translate_m68k_arith(opts, inst, X|N|Z|V|C, &src_op, &dst_op);
1427 if (src_op.mode == MODE_REG_DIRECT) { 1582 break;
1428 if (dst_op.mode == MODE_REG_DIRECT) { 1583 case M68K_ADDX:
1429 add_rr(code, src_op.base, dst_op.base, size); 1584 case M68K_SUBX:
1430 } else { 1585 //z flag is special cased in translate_m68k_arith
1431 add_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size); 1586 translate_m68k_arith(opts, inst, X|N|V|C, &src_op, &dst_op);
1432 } 1587 break;
1433 } else if (src_op.mode == MODE_REG_DISPLACE8) {
1434 add_rdispr(code, src_op.base, src_op.disp, dst_op.base, size);
1435 } else {
1436 if (dst_op.mode == MODE_REG_DIRECT) {
1437 add_ir(code, src_op.disp, dst_op.base, size);
1438 } else {
1439 add_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, size);
1440 }
1441 }
1442 if (inst->dst.addr_mode != MODE_AREG) {
1443 update_flags(opts, X|N|Z|V|C);
1444 }
1445 m68k_save_result(inst, opts);
1446 break;
1447 case M68K_ADDX: {
1448 cycles(&opts->gen, BUS);
1449 flag_to_carry(opts, FLAG_X);
1450 if (src_op.mode == MODE_REG_DIRECT) {
1451 if (dst_op.mode == MODE_REG_DIRECT) {
1452 adc_rr(code, src_op.base, dst_op.base, inst->extra.size);
1453 } else {
1454 adc_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, inst->extra.size);
1455 }
1456 } else if (src_op.mode == MODE_REG_DISPLACE8) {
1457 adc_rdispr(code, src_op.base, src_op.disp, dst_op.base, inst->extra.size);
1458 } else {
1459 if (dst_op.mode == MODE_REG_DIRECT) {
1460 adc_ir(code, src_op.disp, dst_op.base, inst->extra.size);
1461 } else {
1462 adc_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
1463 }
1464 }
1465 set_flag_cond(opts, CC_C, FLAG_C);
1466
1467 check_alloc_code(code, 2*MAX_INST_LEN);
1468 code_ptr after_flag_set = code->cur + 1;
1469 jcc(code, CC_Z, code->cur + 2);
1470 set_flag(opts, 0, FLAG_Z);
1471 *after_flag_set = code->cur - (after_flag_set+1);
1472 set_flag_cond(opts, CC_S, FLAG_N);
1473 set_flag_cond(opts, CC_O, FLAG_V);
1474 if (opts->flag_regs[FLAG_C] >= 0) {
1475 flag_to_flag(opts, FLAG_C, FLAG_X);
1476 } else {
1477 set_flag_cond(opts, CC_C, FLAG_X);
1478 }
1479 m68k_save_result(inst, opts);
1480 break;
1481 }
1482 case M68K_AND: 1588 case M68K_AND:
1483 cycles(&opts->gen, BUS); 1589 case M68K_EOR:
1484 if (src_op.mode == MODE_REG_DIRECT) { 1590 case M68K_OR:
1485 if (dst_op.mode == MODE_REG_DIRECT) { 1591 translate_m68k_arith(opts, inst, N|Z|V0|C0, &src_op, &dst_op);
1486 and_rr(code, src_op.base, dst_op.base, inst->extra.size);
1487 } else {
1488 and_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, inst->extra.size);
1489 }
1490 } else if (src_op.mode == MODE_REG_DISPLACE8) {
1491 and_rdispr(code, src_op.base, src_op.disp, dst_op.base, inst->extra.size);
1492 } else {
1493 if (dst_op.mode == MODE_REG_DIRECT) {
1494 and_ir(code, src_op.disp, dst_op.base, inst->extra.size);
1495 } else {
1496 and_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
1497 }
1498 }
1499 update_flags(opts, N|Z|V0|C0);
1500 m68k_save_result(inst, opts);
1501 break; 1592 break;
1502 case M68K_ANDI_CCR: 1593 case M68K_ANDI_CCR:
1503 case M68K_ANDI_SR: { 1594 case M68K_ANDI_SR: {
1504 cycles(&opts->gen, 20); 1595 cycles(&opts->gen, 20);
1505 //TODO: If ANDI to SR, trap if not in supervisor mode 1596 //TODO: If ANDI to SR, trap if not in supervisor mode
1801 pop_r(code, RDX); 1892 pop_r(code, RDX);
1802 set_flag(opts, 1, FLAG_V); 1893 set_flag(opts, 1, FLAG_V);
1803 *end_off = code->cur - (end_off + 1); 1894 *end_off = code->cur - (end_off + 1);
1804 break; 1895 break;
1805 } 1896 }
1806 case M68K_EOR:
1807 cycles(&opts->gen, BUS);
1808 if (src_op.mode == MODE_REG_DIRECT) {
1809 if (dst_op.mode == MODE_REG_DIRECT) {
1810 xor_rr(code, src_op.base, dst_op.base, inst->extra.size);
1811 } else {
1812 xor_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, inst->extra.size);
1813 }
1814 } else if (src_op.mode == MODE_REG_DISPLACE8) {
1815 xor_rdispr(code, src_op.base, src_op.disp, dst_op.base, inst->extra.size);
1816 } else {
1817 if (dst_op.mode == MODE_REG_DIRECT) {
1818 xor_ir(code, src_op.disp, dst_op.base, inst->extra.size);
1819 } else {
1820 xor_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
1821 }
1822 }
1823 update_flags(opts, N|Z|V0|C0);
1824 m68k_save_result(inst, opts);
1825 break;
1826 case M68K_EORI_CCR: 1897 case M68K_EORI_CCR:
1827 case M68K_EORI_SR: 1898 case M68K_EORI_SR:
1828 cycles(&opts->gen, 20); 1899 cycles(&opts->gen, 20);
1829 //TODO: If ANDI to SR, trap if not in supervisor mode 1900 //TODO: If ANDI to SR, trap if not in supervisor mode
1830 if (inst->src.params.immed & 0x1) { 1901 if (inst->src.params.immed & 0x1) {
1983 cmp_ir(code, 0, dst_reg, SZ_D); 2054 cmp_ir(code, 0, dst_reg, SZ_D);
1984 update_flags(opts, N|Z|V0|C0); 2055 update_flags(opts, N|Z|V0|C0);
1985 break; 2056 break;
1986 //case M68K_NBCD: 2057 //case M68K_NBCD:
1987 case M68K_NEG: 2058 case M68K_NEG:
1988 cycles(&opts->gen, BUS); 2059 translate_m68k_unary(opts, inst, X|N|Z|V|C, &dst_op);
1989 if (dst_op.mode == MODE_REG_DIRECT) {
1990 neg_r(code, dst_op.base, inst->extra.size);
1991 } else {
1992 neg_rdisp(code, dst_op.base, dst_op.disp, inst->extra.size);
1993 }
1994 update_flags(opts, X|N|Z|V|C);
1995 m68k_save_result(inst, opts);
1996 break; 2060 break;
1997 case M68K_NEGX: { 2061 case M68K_NEGX: {
1998 cycles(&opts->gen, BUS); 2062 cycles(&opts->gen, BUS);
1999 if (dst_op.mode == MODE_REG_DIRECT) { 2063 if (dst_op.mode == MODE_REG_DIRECT) {
2000 if (dst_op.base == opts->gen.scratch1) { 2064 if (dst_op.base == opts->gen.scratch1) {
2033 } 2097 }
2034 case M68K_NOP: 2098 case M68K_NOP:
2035 cycles(&opts->gen, BUS); 2099 cycles(&opts->gen, BUS);
2036 break; 2100 break;
2037 case M68K_NOT: 2101 case M68K_NOT:
2038 if (dst_op.mode == MODE_REG_DIRECT) { 2102 translate_m68k_unary(opts, inst, N|Z|V0|C0, &dst_op);
2039 not_r(code, dst_op.base, inst->extra.size);
2040 cmp_ir(code, 0, dst_op.base, inst->extra.size);
2041 } else {
2042 not_rdisp(code, dst_op.base, dst_op.disp, inst->extra.size);
2043 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size);
2044 }
2045
2046 update_flags(opts, N|Z|V0|C0);
2047 m68k_save_result(inst, opts);
2048 break;
2049 case M68K_OR:
2050 cycles(&opts->gen, BUS);
2051 if (src_op.mode == MODE_REG_DIRECT) {
2052 if (dst_op.mode == MODE_REG_DIRECT) {
2053 or_rr(code, src_op.base, dst_op.base, inst->extra.size);
2054 } else {
2055 or_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, inst->extra.size);
2056 }
2057 } else if (src_op.mode == MODE_REG_DISPLACE8) {
2058 or_rdispr(code, src_op.base, src_op.disp, dst_op.base, inst->extra.size);
2059 } else {
2060 if (dst_op.mode == MODE_REG_DIRECT) {
2061 or_ir(code, src_op.disp, dst_op.base, inst->extra.size);
2062 } else {
2063 or_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
2064 }
2065 }
2066 update_flags(opts, N|Z|V0|C0);
2067 m68k_save_result(inst, opts);
2068 break; 2103 break;
2069 case M68K_ORI_CCR: 2104 case M68K_ORI_CCR:
2070 case M68K_ORI_SR: 2105 case M68K_ORI_SR:
2071 cycles(&opts->gen, 20); 2106 cycles(&opts->gen, 20);
2072 //TODO: If ORI to SR, trap if not in supervisor mode 2107 //TODO: If ORI to SR, trap if not in supervisor mode
2103 #endif 2138 #endif
2104 call(code, (code_ptr)print_regs_exit); 2139 call(code, (code_ptr)print_regs_exit);
2105 break; 2140 break;
2106 case M68K_ROL: 2141 case M68K_ROL:
2107 case M68K_ROR: 2142 case M68K_ROR:
2108 set_flag(opts, 0, FLAG_V); 2143 case M68K_ROXL:
2144 case M68K_ROXR: {
2145 int32_t init_flags = C|V0;
2109 if (inst->src.addr_mode == MODE_UNUSED) { 2146 if (inst->src.addr_mode == MODE_UNUSED) {
2110 cycles(&opts->gen, BUS); 2147 cycles(&opts->gen, BUS);
2111 //Memory rotate 2148 //Memory rotate
2112 if (inst->op == M68K_ROL) { 2149 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2113 rol_ir(code, 1, dst_op.base, inst->extra.size); 2150 flag_to_carry(opts, FLAG_X);
2114 } else { 2151 init_flags |= X;
2115 ror_ir(code, 1, dst_op.base, inst->extra.size); 2152 }
2116 } 2153 op_ir(code, inst, 1, dst_op.base, inst->extra.size);
2117 set_flag_cond(opts, CC_C, FLAG_C); 2154 update_flags(opts, init_flags);
2118 cmp_ir(code, 0, dst_op.base, inst->extra.size); 2155 cmp_ir(code, 0, dst_op.base, inst->extra.size);
2119 set_flag_cond(opts, CC_Z, FLAG_Z); 2156 update_flags(opts, Z|N);
2120 set_flag_cond(opts, CC_S, FLAG_N);
2121 m68k_save_result(inst, opts); 2157 m68k_save_result(inst, opts);
2122 } else { 2158 } else {
2123 if (src_op.mode == MODE_IMMED) { 2159 if (src_op.mode == MODE_IMMED) {
2124 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2); 2160 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2);
2161 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2162 flag_to_carry(opts, FLAG_X);
2163 init_flags |= X;
2164 }
2125 if (dst_op.mode == MODE_REG_DIRECT) { 2165 if (dst_op.mode == MODE_REG_DIRECT) {
2126 if (inst->op == M68K_ROL) { 2166 op_ir(code, inst, src_op.disp, dst_op.base, inst->extra.size);
2127 rol_ir(code, src_op.disp, dst_op.base, inst->extra.size);
2128 } else {
2129 ror_ir(code, src_op.disp, dst_op.base, inst->extra.size);
2130 }
2131 } else { 2167 } else {
2132 if (inst->op == M68K_ROL) { 2168 op_irdisp(code, inst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
2133 rol_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); 2169 }
2134 } else { 2170 update_flags(opts, init_flags);
2135 ror_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
2136 }
2137 }
2138 set_flag_cond(opts, CC_C, FLAG_C);
2139 } else { 2171 } else {
2140 if (src_op.mode == MODE_REG_DIRECT) { 2172 if (src_op.mode == MODE_REG_DIRECT) {
2141 if (src_op.base != opts->gen.scratch1) { 2173 if (src_op.base != opts->gen.scratch1) {
2142 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_B); 2174 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_B);
2143 } 2175 }
2150 add_rr(code, opts->gen.scratch1, CYCLES, SZ_D); 2182 add_rr(code, opts->gen.scratch1, CYCLES, SZ_D);
2151 add_rr(code, opts->gen.scratch1, CYCLES, SZ_D); 2183 add_rr(code, opts->gen.scratch1, CYCLES, SZ_D);
2152 cmp_ir(code, 32, opts->gen.scratch1, SZ_B); 2184 cmp_ir(code, 32, opts->gen.scratch1, SZ_B);
2153 norm_off = code->cur + 1; 2185 norm_off = code->cur + 1;
2154 jcc(code, CC_L, code->cur + 2); 2186 jcc(code, CC_L, code->cur + 2);
2155 sub_ir(code, 32, opts->gen.scratch1, SZ_B); 2187 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2188 flag_to_carry(opts, FLAG_X);
2189 init_flags |= X;
2190 } else {
2191 sub_ir(code, 32, opts->gen.scratch1, SZ_B);
2192 }
2156 if (dst_op.mode == MODE_REG_DIRECT) { 2193 if (dst_op.mode == MODE_REG_DIRECT) {
2157 if (inst->op == M68K_ROL) { 2194 op_ir(code, inst, 31, dst_op.base, inst->extra.size);
2158 rol_ir(code, 31, dst_op.base, inst->extra.size); 2195 op_ir(code, inst, 1, dst_op.base, inst->extra.size);
2159 rol_ir(code, 1, dst_op.base, inst->extra.size);
2160 } else {
2161 ror_ir(code, 31, dst_op.base, inst->extra.size);
2162 ror_ir(code, 1, dst_op.base, inst->extra.size);
2163 }
2164 } else { 2196 } else {
2165 if (inst->op == M68K_ROL) { 2197 op_irdisp(code, inst, 31, dst_op.base, dst_op.disp, inst->extra.size);
2166 rol_irdisp(code, 31, dst_op.base, dst_op.disp, inst->extra.size); 2198 op_irdisp(code, inst, 1, dst_op.base, dst_op.disp, inst->extra.size);
2167 rol_irdisp(code, 1, dst_op.base, dst_op.disp, inst->extra.size); 2199 }
2168 } else { 2200
2169 ror_irdisp(code, 31, dst_op.base, dst_op.disp, inst->extra.size); 2201 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2170 ror_irdisp(code, 1, dst_op.base, dst_op.disp, inst->extra.size); 2202 set_flag_cond(opts, CC_C, FLAG_X);
2171 } 2203 sub_ir(code, 32, opts->gen.scratch1, SZ_B);
2172 } 2204 *norm_off = code->cur - (norm_off+1);
2173 *norm_off = code->cur - (norm_off+1); 2205 flag_to_carry(opts, FLAG_X);
2206 } else {
2207 *norm_off = code->cur - (norm_off+1);
2208 }
2174 if (dst_op.mode == MODE_REG_DIRECT) { 2209 if (dst_op.mode == MODE_REG_DIRECT) {
2175 if (inst->op == M68K_ROL) { 2210 op_r(code, inst, dst_op.base, inst->extra.size);
2176 rol_clr(code, dst_op.base, inst->extra.size);
2177 } else {
2178 ror_clr(code, dst_op.base, inst->extra.size);
2179 }
2180 } else { 2211 } else {
2181 if (inst->op == M68K_ROL) { 2212 op_rdisp(code, inst, dst_op.base, dst_op.disp, inst->extra.size);
2182 rol_clrdisp(code, dst_op.base, dst_op.disp, inst->extra.size); 2213 }
2183 } else { 2214 update_flags(opts, init_flags);
2184 ror_clrdisp(code, dst_op.base, dst_op.disp, inst->extra.size);
2185 }
2186 }
2187 set_flag_cond(opts, CC_C, FLAG_C);
2188 end_off = code->cur + 1; 2215 end_off = code->cur + 1;
2189 jmp(code, code->cur + 2); 2216 jmp(code, code->cur + 2);
2190 *zero_off = code->cur - (zero_off+1); 2217 *zero_off = code->cur - (zero_off+1);
2191 set_flag(opts, 0, FLAG_C); 2218 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2219 //Carry flag is set to X flag when count is 0, this is different from ROR/ROL
2220 flag_to_flag(opts, FLAG_X, FLAG_C);
2221 } else {
2222 set_flag(opts, 0, FLAG_C);
2223 }
2192 *end_off = code->cur - (end_off+1); 2224 *end_off = code->cur - (end_off+1);
2193 } 2225 }
2194 if (dst_op.mode == MODE_REG_DIRECT) { 2226 if (dst_op.mode == MODE_REG_DIRECT) {
2195 cmp_ir(code, 0, dst_op.base, inst->extra.size); 2227 cmp_ir(code, 0, dst_op.base, inst->extra.size);
2196 } else { 2228 } else {
2197 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size); 2229 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size);
2198 } 2230 }
2199 set_flag_cond(opts, CC_Z, FLAG_Z); 2231 update_flags(opts, Z|N);
2200 set_flag_cond(opts, CC_S, FLAG_N); 2232 }
2201 } 2233 break;
2202 break; 2234 }
2203 case M68K_ROXL:
2204 case M68K_ROXR:
2205 set_flag(opts, 0, FLAG_V);
2206 if (inst->src.addr_mode == MODE_UNUSED) {
2207 cycles(&opts->gen, BUS);
2208 //Memory rotate
2209 flag_to_carry(opts, FLAG_X);
2210 if (inst->op == M68K_ROXL) {
2211 rcl_ir(code, 1, dst_op.base, inst->extra.size);
2212 } else {
2213 rcr_ir(code, 1, dst_op.base, inst->extra.size);
2214 }
2215 set_flag_cond(opts, CC_C, FLAG_C);
2216 if (opts->flag_regs[FLAG_C] < 0) {
2217 set_flag_cond(opts, CC_C, FLAG_X);
2218 }
2219 cmp_ir(code, 0, dst_op.base, inst->extra.size);
2220 set_flag_cond(opts, CC_Z, FLAG_Z);
2221 set_flag_cond(opts, CC_S, FLAG_N);
2222 if (opts->flag_regs[FLAG_C] >= 0) {
2223 flag_to_flag(opts, FLAG_C, FLAG_X);
2224 }
2225 m68k_save_result(inst, opts);
2226 } else {
2227 if (src_op.mode == MODE_IMMED) {
2228 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2);
2229 flag_to_carry(opts, FLAG_X);
2230 if (dst_op.mode == MODE_REG_DIRECT) {
2231 if (inst->op == M68K_ROXL) {
2232 rcl_ir(code, src_op.disp, dst_op.base, inst->extra.size);
2233 } else {
2234 rcr_ir(code, src_op.disp, dst_op.base, inst->extra.size);
2235 }
2236 } else {
2237 if (inst->op == M68K_ROXL) {
2238 rcl_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
2239 } else {
2240 rcr_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
2241 }
2242 }
2243 set_flag_cond(opts, CC_C, FLAG_C);
2244 if (opts->flag_regs[FLAG_C] >= 0) {
2245 flag_to_flag(opts, FLAG_C, FLAG_X);
2246 } else {
2247 set_flag_cond(opts, CC_C, FLAG_X);
2248 }
2249 } else {
2250 if (src_op.mode == MODE_REG_DIRECT) {
2251 if (src_op.base != opts->gen.scratch1) {
2252 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_B);
2253 }
2254 } else {
2255 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B);
2256 }
2257 and_ir(code, 63, opts->gen.scratch1, SZ_D);
2258 zero_off = code->cur + 1;
2259 jcc(code, CC_Z, code->cur + 2);
2260 add_rr(code, opts->gen.scratch1, CYCLES, SZ_D);
2261 add_rr(code, opts->gen.scratch1, CYCLES, SZ_D);
2262 cmp_ir(code, 32, opts->gen.scratch1, SZ_B);
2263 norm_off = code->cur + 1;
2264 jcc(code, CC_L, code->cur + 2);
2265 flag_to_carry(opts, FLAG_X);
2266 if (dst_op.mode == MODE_REG_DIRECT) {
2267 if (inst->op == M68K_ROXL) {
2268 rcl_ir(code, 31, dst_op.base, inst->extra.size);
2269 rcl_ir(code, 1, dst_op.base, inst->extra.size);
2270 } else {
2271 rcr_ir(code, 31, dst_op.base, inst->extra.size);
2272 rcr_ir(code, 1, dst_op.base, inst->extra.size);
2273 }
2274 } else {
2275 if (inst->op == M68K_ROXL) {
2276 rcl_irdisp(code, 31, dst_op.base, dst_op.disp, inst->extra.size);
2277 rcl_irdisp(code, 1, dst_op.base, dst_op.disp, inst->extra.size);
2278 } else {
2279 rcr_irdisp(code, 31, dst_op.base, dst_op.disp, inst->extra.size);
2280 rcr_irdisp(code, 1, dst_op.base, dst_op.disp, inst->extra.size);
2281 }
2282 }
2283 set_flag_cond(opts, CC_C, FLAG_X);
2284 sub_ir(code, 32, opts->gen.scratch1, SZ_B);
2285 *norm_off = code->cur - (norm_off+1);
2286 flag_to_carry(opts, FLAG_X);
2287 if (dst_op.mode == MODE_REG_DIRECT) {
2288 if (inst->op == M68K_ROXL) {
2289 rcl_clr(code, dst_op.base, inst->extra.size);
2290 } else {
2291 rcr_clr(code, dst_op.base, inst->extra.size);
2292 }
2293 } else {
2294 if (inst->op == M68K_ROXL) {
2295 rcl_clrdisp(code, dst_op.base, dst_op.disp, inst->extra.size);
2296 } else {
2297 rcr_clrdisp(code, dst_op.base, dst_op.disp, inst->extra.size);
2298 }
2299 }
2300 set_flag_cond(opts, CC_C, FLAG_C);
2301 if (opts->flag_regs[FLAG_C] >= 0) {
2302 flag_to_flag(opts, FLAG_C, FLAG_X);
2303 } else {
2304 set_flag_cond(opts, CC_C, FLAG_X);
2305 }
2306 end_off = code->cur + 1;
2307 jmp(code, code->cur + 2);
2308 *zero_off = code->cur - (zero_off+1);
2309 //Carry flag is set to X flag when count is 0, this is different from ROR/ROL
2310 flag_to_flag(opts, FLAG_X, FLAG_C);
2311 *end_off = code->cur - (end_off+1);
2312 }
2313 if (dst_op.mode == MODE_REG_DIRECT) {
2314 cmp_ir(code, 0, dst_op.base, inst->extra.size);
2315 } else {
2316 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size);
2317 }
2318 set_flag_cond(opts, CC_Z, FLAG_Z);
2319 set_flag_cond(opts, CC_S, FLAG_N);
2320 }
2321 break;
2322 case M68K_RTE: 2235 case M68K_RTE:
2323 //TODO: Trap if not in system mode 2236 //TODO: Trap if not in system mode
2324 //Read saved SR 2237 //Read saved SR
2325 areg_to_native(opts, 7, opts->gen.scratch1); 2238 areg_to_native(opts, 7, opts->gen.scratch1);
2326 call(code, opts->read_16); 2239 call(code, opts->read_16);
2408 *after_cycle_up = code->cur - (after_cycle_up+1); 2321 *after_cycle_up = code->cur - (after_cycle_up+1);
2409 cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D); 2322 cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D);
2410 jcc(code, CC_C, loop_top); 2323 jcc(code, CC_C, loop_top);
2411 break; 2324 break;
2412 } 2325 }
2413 case M68K_SUB:
2414 size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size;
2415 cycles(&opts->gen, BUS);
2416 if (src_op.mode == MODE_REG_DIRECT) {
2417 if (dst_op.mode == MODE_REG_DIRECT) {
2418 sub_rr(code, src_op.base, dst_op.base, size);
2419 } else {
2420 sub_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size);
2421 }
2422 } else if (src_op.mode == MODE_REG_DISPLACE8) {
2423 sub_rdispr(code, src_op.base, src_op.disp, dst_op.base, size);
2424 } else {
2425 if (dst_op.mode == MODE_REG_DIRECT) {
2426 sub_ir(code, src_op.disp, dst_op.base, size);
2427 } else {
2428 sub_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, size);
2429 }
2430 }
2431 if (inst->dst.addr_mode != MODE_AREG) {
2432 update_flags(opts, X|N|Z|V|C);
2433 }
2434 m68k_save_result(inst, opts);
2435 break;
2436 case M68K_SUBX: {
2437 cycles(&opts->gen, BUS);
2438 flag_to_carry(opts, FLAG_X);
2439 if (src_op.mode == MODE_REG_DIRECT) {
2440 if (dst_op.mode == MODE_REG_DIRECT) {
2441 sbb_rr(code, src_op.base, dst_op.base, inst->extra.size);
2442 } else {
2443 sbb_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, inst->extra.size);
2444 }
2445 } else if (src_op.mode == MODE_REG_DISPLACE8) {
2446 sbb_rdispr(code, src_op.base, src_op.disp, dst_op.base, inst->extra.size);
2447 } else {
2448 if (dst_op.mode == MODE_REG_DIRECT) {
2449 sbb_ir(code, src_op.disp, dst_op.base, inst->extra.size);
2450 } else {
2451 sbb_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
2452 }
2453 }
2454 set_flag_cond(opts, CC_C, FLAG_C);
2455 if (opts->flag_regs[FLAG_C] < 0) {
2456 set_flag_cond(opts, CC_C, FLAG_X);
2457 }
2458 code_ptr after_flag_set = code->cur + 1;
2459 jcc(code, CC_Z, code->cur + 2);
2460 set_flag(opts, 0, FLAG_Z);
2461 *after_flag_set = code->cur - (after_flag_set+1);
2462 set_flag_cond(opts, CC_S, FLAG_N);
2463 set_flag_cond(opts, CC_O, FLAG_V);
2464 if (opts->flag_regs[FLAG_C] >= 0) {
2465 flag_to_flag(opts, FLAG_C, FLAG_X);
2466 }
2467 m68k_save_result(inst, opts);
2468 break;
2469 }
2470 case M68K_SWAP: 2326 case M68K_SWAP:
2471 cycles(&opts->gen, BUS); 2327 cycles(&opts->gen, BUS);
2472 if (src_op.mode == MODE_REG_DIRECT) { 2328 if (src_op.mode == MODE_REG_DIRECT) {
2473 rol_ir(code, 16, src_op.base, SZ_D); 2329 rol_ir(code, 16, src_op.base, SZ_D);
2474 cmp_ir(code, 0, src_op.base, SZ_D); 2330 cmp_ir(code, 0, src_op.base, SZ_D);
2483 case M68K_TRAP: 2339 case M68K_TRAP:
2484 translate_m68k_trap(opts, inst); 2340 translate_m68k_trap(opts, inst);
2485 break; 2341 break;
2486 //case M68K_TRAPV: 2342 //case M68K_TRAPV:
2487 case M68K_TST: 2343 case M68K_TST:
2488 cycles(&opts->gen, BUS); 2344 translate_m68k_unary(opts, inst, N|Z|V0|C0, &src_op);
2489 if (src_op.mode == MODE_REG_DIRECT) {
2490 cmp_ir(code, 0, src_op.base, inst->extra.size);
2491 } else { //M68000 doesn't support immedate operand for tst, so this must be MODE_REG_DISPLACE8
2492 cmp_irdisp(code, 0, src_op.base, src_op.disp, inst->extra.size);
2493 }
2494 update_flags(opts, N|Z|V0|C0);
2495 break; 2345 break;
2496 default: 2346 default:
2497 m68k_disasm(inst, disasm_buf); 2347 m68k_disasm(inst, disasm_buf);
2498 printf("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op); 2348 printf("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op);
2499 exit(1); 2349 exit(1);