comparison m68k_core_x86.c @ 582:c05fcbfe1b1a

Refactored translate_m68k so that it contains no host-cpu specific code and moved it to m68k_core.c
author Michael Pavone <pavone@retrodev.com>
date Fri, 07 Mar 2014 17:42:29 -0800
parents 9f40aa5243c2
children 819921b76b4b
comparison
equal deleted inserted replaced
581:9f40aa5243c2 582:c05fcbfe1b1a
333 { 333 {
334 areg_to_native(opts, op->params.regs.pri, native_reg); 334 areg_to_native(opts, op->params.regs.pri, native_reg);
335 calc_index_disp8(opts, op, native_reg); 335 calc_index_disp8(opts, op, native_reg);
336 } 336 }
337 337
338 void translate_m68k_op(m68kinst * inst, x86_ea * ea, m68k_options * opts, uint8_t dst) 338 void translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst)
339 { 339 {
340 code_info *code = &opts->gen.code; 340 code_info *code = &opts->gen.code;
341 m68k_op_info *op = dst ? &inst->dst : &inst->src; 341 m68k_op_info *op = dst ? &inst->dst : &inst->src;
342 int8_t reg = native_reg(op, opts); 342 int8_t reg = native_reg(op, opts);
343 uint8_t sec_reg; 343 uint8_t sec_reg;
534 code_info *code = &opts->gen.code; 534 code_info *code = &opts->gen.code;
535 int8_t reg, flags_reg, sec_reg; 535 int8_t reg, flags_reg, sec_reg;
536 uint8_t dir = 0; 536 uint8_t dir = 0;
537 int32_t offset; 537 int32_t offset;
538 int32_t inc_amount, dec_amount; 538 int32_t inc_amount, dec_amount;
539 x86_ea src; 539 host_ea src;
540 translate_m68k_op(inst, &src, opts, 0); 540 translate_m68k_op(inst, &src, opts, 0);
541 reg = native_reg(&(inst->dst), opts); 541 reg = native_reg(&(inst->dst), opts);
542 542
543 if (inst->dst.addr_mode != MODE_AREG) { 543 if (inst->dst.addr_mode != MODE_AREG) {
544 if (src.mode == MODE_REG_DIRECT) { 544 if (src.mode == MODE_REG_DIRECT) {
849 if (reg >= 0) { 849 if (reg >= 0) {
850 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 6 : 4)); 850 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 6 : 4));
851 xor_rr(code, reg, reg, inst->extra.size); 851 xor_rr(code, reg, reg, inst->extra.size);
852 return; 852 return;
853 } 853 }
854 x86_ea dst_op; 854 host_ea dst_op;
855 //TODO: fix timing 855 //TODO: fix timing
856 translate_m68k_op(inst, &dst_op, opts, 1); 856 translate_m68k_op(inst, &dst_op, opts, 1);
857 if (dst_op.mode == MODE_REG_DIRECT) { 857 if (dst_op.mode == MODE_REG_DIRECT) {
858 xor_rr(code, dst_op.base, dst_op.base, inst->extra.size); 858 xor_rr(code, dst_op.base, dst_op.base, inst->extra.size);
859 } else { 859 } else {
863 } 863 }
864 864
865 void translate_m68k_ext(m68k_options * opts, m68kinst * inst) 865 void translate_m68k_ext(m68k_options * opts, m68kinst * inst)
866 { 866 {
867 code_info *code = &opts->gen.code; 867 code_info *code = &opts->gen.code;
868 x86_ea dst_op; 868 host_ea dst_op;
869 uint8_t dst_size = inst->extra.size; 869 uint8_t dst_size = inst->extra.size;
870 inst->extra.size--; 870 inst->extra.size--;
871 translate_m68k_op(inst, &dst_op, opts, 1); 871 translate_m68k_op(inst, &dst_op, opts, 1);
872 if (dst_op.mode == MODE_REG_DIRECT) { 872 if (dst_op.mode == MODE_REG_DIRECT) {
873 movsx_rr(code, dst_op.base, dst_op.base, inst->extra.size, dst_size); 873 movsx_rr(code, dst_op.base, dst_op.base, inst->extra.size, dst_size);
951 951
952 void translate_m68k_scc(m68k_options * opts, m68kinst * inst) 952 void translate_m68k_scc(m68k_options * opts, m68kinst * inst)
953 { 953 {
954 code_info *code = &opts->gen.code; 954 code_info *code = &opts->gen.code;
955 uint8_t cond = inst->extra.cond; 955 uint8_t cond = inst->extra.cond;
956 x86_ea dst_op; 956 host_ea dst_op;
957 inst->extra.size = OPSIZE_BYTE; 957 inst->extra.size = OPSIZE_BYTE;
958 translate_m68k_op(inst, &dst_op, opts, 1); 958 translate_m68k_op(inst, &dst_op, opts, 1);
959 if (cond == COND_TRUE || cond == COND_FALSE) { 959 if (cond == COND_TRUE || cond == COND_FALSE) {
960 if ((inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) && inst->extra.cond == COND_TRUE) { 960 if ((inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) && inst->extra.cond == COND_TRUE) {
961 cycles(&opts->gen, 6); 961 cycles(&opts->gen, 6);
1125 typedef void (*shift_ir_t)(code_info *code, uint8_t val, uint8_t dst, uint8_t size); 1125 typedef void (*shift_ir_t)(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
1126 typedef void (*shift_irdisp_t)(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size); 1126 typedef void (*shift_irdisp_t)(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size);
1127 typedef void (*shift_clr_t)(code_info *code, uint8_t dst, uint8_t size); 1127 typedef void (*shift_clr_t)(code_info *code, uint8_t dst, uint8_t size);
1128 typedef void (*shift_clrdisp_t)(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size); 1128 typedef void (*shift_clrdisp_t)(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
1129 1129
1130 void translate_shift(m68k_options * opts, m68kinst * inst, x86_ea *src_op, x86_ea * dst_op, shift_ir_t shift_ir, shift_irdisp_t shift_irdisp, shift_clr_t shift_clr, shift_clrdisp_t shift_clrdisp, shift_ir_t special, shift_irdisp_t special_disp) 1130 void translate_shift(m68k_options * opts, m68kinst * inst, host_ea *src_op, host_ea * dst_op, shift_ir_t shift_ir, shift_irdisp_t shift_irdisp, shift_clr_t shift_clr, shift_clrdisp_t shift_clrdisp, shift_ir_t special, shift_irdisp_t special_disp)
1131 { 1131 {
1132 code_info *code = &opts->gen.code; 1132 code_info *code = &opts->gen.code;
1133 code_ptr end_off = NULL; 1133 code_ptr end_off = NULL;
1134 code_ptr nz_off = NULL; 1134 code_ptr nz_off = NULL;
1135 code_ptr z_off = NULL; 1135 code_ptr z_off = NULL;
1302 case M68K_AND: and_ir(code, val, dst, size); break; 1302 case M68K_AND: and_ir(code, val, dst, size); break;
1303 case M68K_BTST: bt_ir(code, val, dst, size); break; 1303 case M68K_BTST: bt_ir(code, val, dst, size); break;
1304 case M68K_BSET: bts_ir(code, val, dst, size); break; 1304 case M68K_BSET: bts_ir(code, val, dst, size); break;
1305 case M68K_BCLR: btr_ir(code, val, dst, size); break; 1305 case M68K_BCLR: btr_ir(code, val, dst, size); break;
1306 case M68K_BCHG: btc_ir(code, val, dst, size); break; 1306 case M68K_BCHG: btc_ir(code, val, dst, size); break;
1307 case M68K_CMP: cmp_ir(code, val, dst, size); break;
1307 case M68K_EOR: xor_ir(code, val, dst, size); break; 1308 case M68K_EOR: xor_ir(code, val, dst, size); break;
1308 case M68K_OR: or_ir(code, val, dst, size); break; 1309 case M68K_OR: or_ir(code, val, dst, size); break;
1309 case M68K_ROL: rol_ir(code, val, dst, size); break; 1310 case M68K_ROL: rol_ir(code, val, dst, size); break;
1310 case M68K_ROR: ror_ir(code, val, dst, size); break; 1311 case M68K_ROR: ror_ir(code, val, dst, size); break;
1311 case M68K_ROXL: rcl_ir(code, val, dst, size); break; 1312 case M68K_ROXL: rcl_ir(code, val, dst, size); break;
1324 case M68K_AND: and_irdisp(code, val, dst, disp, size); break; 1325 case M68K_AND: and_irdisp(code, val, dst, disp, size); break;
1325 case M68K_BTST: bt_irdisp(code, val, dst, disp, size); break; 1326 case M68K_BTST: bt_irdisp(code, val, dst, disp, size); break;
1326 case M68K_BSET: bts_irdisp(code, val, dst, disp, size); break; 1327 case M68K_BSET: bts_irdisp(code, val, dst, disp, size); break;
1327 case M68K_BCLR: btr_irdisp(code, val, dst, disp, size); break; 1328 case M68K_BCLR: btr_irdisp(code, val, dst, disp, size); break;
1328 case M68K_BCHG: btc_irdisp(code, val, dst, disp, size); break; 1329 case M68K_BCHG: btc_irdisp(code, val, dst, disp, size); break;
1330 case M68K_CMP: cmp_irdisp(code, val, dst, disp, size); break;
1329 case M68K_EOR: xor_irdisp(code, val, dst, disp, size); break; 1331 case M68K_EOR: xor_irdisp(code, val, dst, disp, size); break;
1330 case M68K_OR: or_irdisp(code, val, dst, disp, size); break; 1332 case M68K_OR: or_irdisp(code, val, dst, disp, size); break;
1331 case M68K_ROL: rol_irdisp(code, val, dst, disp, size); break; 1333 case M68K_ROL: rol_irdisp(code, val, dst, disp, size); break;
1332 case M68K_ROR: ror_irdisp(code, val, dst, disp, size); break; 1334 case M68K_ROR: ror_irdisp(code, val, dst, disp, size); break;
1333 case M68K_ROXL: rcl_irdisp(code, val, dst, disp, size); break; 1335 case M68K_ROXL: rcl_irdisp(code, val, dst, disp, size); break;
1346 case M68K_AND: and_rr(code, src, dst, size); break; 1348 case M68K_AND: and_rr(code, src, dst, size); break;
1347 case M68K_BTST: bt_rr(code, src, dst, size); break; 1349 case M68K_BTST: bt_rr(code, src, dst, size); break;
1348 case M68K_BSET: bts_rr(code, src, dst, size); break; 1350 case M68K_BSET: bts_rr(code, src, dst, size); break;
1349 case M68K_BCLR: btr_rr(code, src, dst, size); break; 1351 case M68K_BCLR: btr_rr(code, src, dst, size); break;
1350 case M68K_BCHG: btc_rr(code, src, dst, size); break; 1352 case M68K_BCHG: btc_rr(code, src, dst, size); break;
1353 case M68K_CMP: cmp_rr(code, src, dst, size); break;
1351 case M68K_EOR: xor_rr(code, src, dst, size); break; 1354 case M68K_EOR: xor_rr(code, src, dst, size); break;
1352 case M68K_OR: or_rr(code, src, dst, size); break; 1355 case M68K_OR: or_rr(code, src, dst, size); break;
1353 case M68K_SUB: sub_rr(code, src, dst, size); break; 1356 case M68K_SUB: sub_rr(code, src, dst, size); break;
1354 case M68K_SUBX: sbb_rr(code, src, dst, size); break; 1357 case M68K_SUBX: sbb_rr(code, src, dst, size); break;
1355 } 1358 }
1364 case M68K_AND: and_rrdisp(code, src, dst, disp, size); break; 1367 case M68K_AND: and_rrdisp(code, src, dst, disp, size); break;
1365 case M68K_BTST: bt_rrdisp(code, src, dst, disp, size); break; 1368 case M68K_BTST: bt_rrdisp(code, src, dst, disp, size); break;
1366 case M68K_BSET: bts_rrdisp(code, src, dst, disp, size); break; 1369 case M68K_BSET: bts_rrdisp(code, src, dst, disp, size); break;
1367 case M68K_BCLR: btr_rrdisp(code, src, dst, disp, size); break; 1370 case M68K_BCLR: btr_rrdisp(code, src, dst, disp, size); break;
1368 case M68K_BCHG: btc_rrdisp(code, src, dst, disp, size); break; 1371 case M68K_BCHG: btc_rrdisp(code, src, dst, disp, size); break;
1372 case M68K_CMP: cmp_rrdisp(code, src, dst, disp, size); break;
1369 case M68K_EOR: xor_rrdisp(code, src, dst, disp, size); break; 1373 case M68K_EOR: xor_rrdisp(code, src, dst, disp, size); break;
1370 case M68K_OR: or_rrdisp(code, src, dst, disp, size); break; 1374 case M68K_OR: or_rrdisp(code, src, dst, disp, size); break;
1371 case M68K_SUB: sub_rrdisp(code, src, dst, disp, size); break; 1375 case M68K_SUB: sub_rrdisp(code, src, dst, disp, size); break;
1372 case M68K_SUBX: sbb_rrdisp(code, src, dst, disp, size); break; 1376 case M68K_SUBX: sbb_rrdisp(code, src, dst, disp, size); break;
1373 } 1377 }
1378 switch (inst->op) 1382 switch (inst->op)
1379 { 1383 {
1380 case M68K_ADD: add_rdispr(code, src, disp, dst, size); break; 1384 case M68K_ADD: add_rdispr(code, src, disp, dst, size); break;
1381 case M68K_ADDX: adc_rdispr(code, src, disp, dst, size); break; 1385 case M68K_ADDX: adc_rdispr(code, src, disp, dst, size); break;
1382 case M68K_AND: and_rdispr(code, src, disp, dst, size); break; 1386 case M68K_AND: and_rdispr(code, src, disp, dst, size); break;
1387 case M68K_CMP: cmp_rdispr(code, src, disp, dst, size); break;
1383 case M68K_EOR: xor_rdispr(code, src, disp, dst, size); break; 1388 case M68K_EOR: xor_rdispr(code, src, disp, dst, size); break;
1384 case M68K_OR: or_rdispr(code, src, disp, dst, size); break; 1389 case M68K_OR: or_rdispr(code, src, disp, dst, size); break;
1385 case M68K_SUB: sub_rdispr(code, src, disp, dst, size); break; 1390 case M68K_SUB: sub_rdispr(code, src, disp, dst, size); break;
1386 case M68K_SUBX: sbb_rdispr(code, src, disp, dst, size); break; 1391 case M68K_SUBX: sbb_rdispr(code, src, disp, dst, size); break;
1387 } 1392 }
1388 } 1393 }
1389 1394
1390 void translate_m68k_arith(m68k_options *opts, m68kinst * inst, uint32_t flag_mask, x86_ea *src_op, x86_ea *dst_op) 1395 void translate_m68k_arith(m68k_options *opts, m68kinst * inst, uint32_t flag_mask, host_ea *src_op, host_ea *dst_op)
1391 { 1396 {
1392 code_info *code = &opts->gen.code; 1397 code_info *code = &opts->gen.code;
1393 cycles(&opts->gen, BUS); 1398 cycles(&opts->gen, BUS);
1394 if (inst->op == M68K_ADDX || inst->op == M68K_SUBX) { 1399 if (inst->op == M68K_ADDX || inst->op == M68K_SUBX) {
1395 flag_to_carry(opts, FLAG_X); 1400 flag_to_carry(opts, FLAG_X);
1427 1432
1428 void translate_m68k_cmp(m68k_options * opts, m68kinst * inst) 1433 void translate_m68k_cmp(m68k_options * opts, m68kinst * inst)
1429 { 1434 {
1430 code_info *code = &opts->gen.code; 1435 code_info *code = &opts->gen.code;
1431 uint8_t size = inst->extra.size; 1436 uint8_t size = inst->extra.size;
1432 x86_ea src_op, dst_op; 1437 host_ea src_op, dst_op;
1433 translate_m68k_op(inst, &src_op, opts, 0); 1438 translate_m68k_op(inst, &src_op, opts, 0);
1434 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { 1439 if (inst->dst.addr_mode == MODE_AREG_POSTINC) {
1435 push_r(code, opts->gen.scratch1); 1440 push_r(code, opts->gen.scratch1);
1436 translate_m68k_op(inst, &dst_op, opts, 1); 1441 translate_m68k_op(inst, &dst_op, opts, 1);
1437 pop_r(code, opts->gen.scratch2); 1442 pop_r(code, opts->gen.scratch2);
1473 case M68K_SWAP: rol_irdisp(code, 16, dst, disp, SZ_D); cmp_irdisp(code, 0, dst, disp, SZ_D); break; 1478 case M68K_SWAP: rol_irdisp(code, 16, dst, disp, SZ_D); cmp_irdisp(code, 0, dst, disp, SZ_D); break;
1474 case M68K_TST: cmp_irdisp(code, 0, dst, disp, size); break; 1479 case M68K_TST: cmp_irdisp(code, 0, dst, disp, size); break;
1475 } 1480 }
1476 } 1481 }
1477 1482
1478 void translate_m68k_unary(m68k_options *opts, m68kinst *inst, uint32_t flag_mask, x86_ea *dst_op) 1483 void translate_m68k_unary(m68k_options *opts, m68kinst *inst, uint32_t flag_mask, host_ea *dst_op)
1479 { 1484 {
1480 code_info *code = &opts->gen.code; 1485 code_info *code = &opts->gen.code;
1481 cycles(&opts->gen, BUS); 1486 cycles(&opts->gen, BUS);
1482 if (dst_op->mode == MODE_REG_DIRECT) { 1487 if (dst_op->mode == MODE_REG_DIRECT) {
1483 op_r(code, inst, dst_op->base, inst->extra.size); 1488 op_r(code, inst, dst_op->base, inst->extra.size);
1486 } 1491 }
1487 update_flags(opts, flag_mask); 1492 update_flags(opts, flag_mask);
1488 m68k_save_result(inst, opts); 1493 m68k_save_result(inst, opts);
1489 } 1494 }
1490 1495
1491 #define BIT_SUPERVISOR 5 1496 void translate_m68k_invalid(m68k_options *opts, m68kinst *inst)
1492 1497 {
1493 void translate_m68k(m68k_options * opts, m68kinst * inst) 1498 code_info *code = &opts->gen.code;
1494 { 1499 if (inst->src.params.immed == 0x7100) {
1495 code_ptr end_off, zero_off, norm_off; 1500 retn(code);
1501 return;
1502 }
1503 mov_ir(code, inst->address, opts->gen.scratch1, SZ_D);
1504 call(code, (code_ptr)m68k_invalid);
1505 }
1506
1507 void translate_m68k_abcd_sbcd(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1508 {
1509 code_info *code = &opts->gen.code;
1510 if (src_op->base != opts->gen.scratch2) {
1511 if (src_op->mode == MODE_REG_DIRECT) {
1512 mov_rr(code, src_op->base, opts->gen.scratch2, SZ_B);
1513 } else {
1514 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch2, SZ_B);
1515 }
1516 }
1517 if (dst_op->base != opts->gen.scratch1) {
1518 if (dst_op->mode == MODE_REG_DIRECT) {
1519 mov_rr(code, dst_op->base, opts->gen.scratch1, SZ_B);
1520 } else {
1521 mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch1, SZ_B);
1522 }
1523 }
1524 flag_to_carry(opts, FLAG_X);
1525 jcc(code, CC_NC, code->cur + 5);
1526 if (inst->op == M68K_ABCD) {
1527 add_ir(code, 1, opts->gen.scratch1, SZ_B);
1528 } else {
1529 sub_ir(code, 1, opts->gen.scratch1, SZ_B);
1530 }
1531 call(code, (code_ptr) (inst->op == M68K_ABCD ? bcd_add : bcd_sub));
1532 reg_to_flag(opts, CH, FLAG_C);
1533 reg_to_flag(opts, CH, FLAG_X);
1534 cmp_ir(code, 0, opts->gen.scratch1, SZ_B);
1535 jcc(code, CC_Z, code->cur + 4);
1536 set_flag(opts, 0, FLAG_Z);
1537 if (dst_op->base != opts->gen.scratch1) {
1538 if (dst_op->mode == MODE_REG_DIRECT) {
1539 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_B);
1540 } else {
1541 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_B);
1542 }
1543 }
1544 m68k_save_result(inst, opts);
1545 }
1546
1547 void translate_m68k_sl(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1548 {
1549 translate_shift(opts, inst, src_op, dst_op, shl_ir, shl_irdisp, shl_clr, shl_clrdisp, shr_ir, shr_irdisp);
1550 }
1551
1552 void translate_m68k_asr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1553 {
1554 translate_shift(opts, inst, src_op, dst_op, sar_ir, sar_irdisp, sar_clr, sar_clrdisp, NULL, NULL);
1555 }
1556
1557 void translate_m68k_lsr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1558 {
1559 translate_shift(opts, inst, src_op, dst_op, shr_ir, shr_irdisp, shr_clr, shr_clrdisp, shl_ir, shl_irdisp);
1560 }
1561
1562 void translate_m68k_bit(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1563 {
1564 code_info *code = &opts->gen.code;
1565 cycles(&opts->gen, inst->extra.size == OPSIZE_BYTE ? 4 : (
1566 inst->op == M68K_BTST ? 6 : (inst->op == M68K_BCLR ? 10 : 8))
1567 );
1568 if (src_op->mode == MODE_IMMED) {
1569 if (inst->extra.size == OPSIZE_BYTE) {
1570 src_op->disp &= 0x7;
1571 }
1572 if (dst_op->mode == MODE_REG_DIRECT) {
1573 op_ir(code, inst, src_op->disp, dst_op->base, inst->extra.size);
1574 } else {
1575 op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size);
1576 }
1577 } else {
1578 if (src_op->mode == MODE_REG_DISPLACE8 || (inst->dst.addr_mode != MODE_REG && src_op->base != opts->gen.scratch1 && src_op->base != opts->gen.scratch2)) {
1579 if (dst_op->base == opts->gen.scratch1) {
1580 push_r(code, opts->gen.scratch2);
1581 if (src_op->mode == MODE_REG_DIRECT) {
1582 mov_rr(code, src_op->base, opts->gen.scratch2, SZ_B);
1583 } else {
1584 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch2, SZ_B);
1585 }
1586 src_op->base = opts->gen.scratch2;
1587 } else {
1588 if (src_op->mode == MODE_REG_DIRECT) {
1589 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_B);
1590 } else {
1591 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_B);
1592 }
1593 src_op->base = opts->gen.scratch1;
1594 }
1595 }
1596 uint8_t size = inst->extra.size;
1597 if (dst_op->mode == MODE_REG_DISPLACE8) {
1598 if (src_op->base != opts->gen.scratch1 && src_op->base != opts->gen.scratch2) {
1599 if (src_op->mode == MODE_REG_DIRECT) {
1600 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_D);
1601 } else {
1602 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_D);
1603 src_op->mode = MODE_REG_DIRECT;
1604 }
1605 src_op->base = opts->gen.scratch1;
1606 }
1607 //b### with register destination is modulo 32
1608 //x86 with a memory destination isn't modulo anything
1609 //so use an and here to force the value to be modulo 32
1610 and_ir(code, 31, opts->gen.scratch1, SZ_D);
1611 } else if(inst->dst.addr_mode != MODE_REG) {
1612 //b### with memory destination is modulo 8
1613 //x86-64 doesn't support 8-bit bit operations
1614 //so we fake it by forcing the bit number to be modulo 8
1615 and_ir(code, 7, src_op->base, SZ_D);
1616 size = SZ_D;
1617 }
1618 if (dst_op->mode == MODE_REG_DIRECT) {
1619 op_rr(code, inst, src_op->base, dst_op->base, size);
1620 } else {
1621 op_rrdisp(code, inst, src_op->base, dst_op->base, dst_op->disp, size);
1622 }
1623 if (src_op->base == opts->gen.scratch2) {
1624 pop_r(code, opts->gen.scratch2);
1625 }
1626 }
1627 //x86 sets the carry flag to the value of the bit tested
1628 //68K sets the zero flag to the complement of the bit tested
1629 set_flag_cond(opts, CC_NC, FLAG_Z);
1630 if (inst->op != M68K_BTST) {
1631 m68k_save_result(inst, opts);
1632 }
1633 }
1634
1635 void translate_m68k_chk(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1636 {
1637 code_info *code = &opts->gen.code;
1638 cycles(&opts->gen, 6);
1639 if (dst_op->mode == MODE_REG_DIRECT) {
1640 cmp_ir(code, 0, dst_op->base, inst->extra.size);
1641 } else {
1642 cmp_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size);
1643 }
1644 uint32_t isize;
1645 switch(inst->src.addr_mode)
1646 {
1647 case MODE_AREG_DISPLACE:
1648 case MODE_AREG_INDEX_DISP8:
1649 case MODE_ABSOLUTE_SHORT:
1650 case MODE_PC_INDEX_DISP8:
1651 case MODE_PC_DISPLACE:
1652 case MODE_IMMEDIATE:
1653 isize = 4;
1654 break;
1655 case MODE_ABSOLUTE:
1656 isize = 6;
1657 break;
1658 default:
1659 isize = 2;
1660 }
1661 //make sure we won't start a new chunk in the middle of these branches
1662 check_alloc_code(code, MAX_INST_LEN * 11);
1663 code_ptr passed = code->cur + 1;
1664 jcc(code, CC_GE, code->cur + 2);
1665 set_flag(opts, 1, FLAG_N);
1666 mov_ir(code, VECTOR_CHK, opts->gen.scratch2, SZ_D);
1667 mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D);
1668 jmp(code, opts->trap);
1669 *passed = code->cur - (passed+1);
1670 if (dst_op->mode == MODE_REG_DIRECT) {
1671 if (src_op->mode == MODE_REG_DIRECT) {
1672 cmp_rr(code, src_op->base, dst_op->base, inst->extra.size);
1673 } else if(src_op->mode == MODE_REG_DISPLACE8) {
1674 cmp_rdispr(code, src_op->base, src_op->disp, dst_op->base, inst->extra.size);
1675 } else {
1676 cmp_ir(code, src_op->disp, dst_op->base, inst->extra.size);
1677 }
1678 } else if(dst_op->mode == MODE_REG_DISPLACE8) {
1679 if (src_op->mode == MODE_REG_DIRECT) {
1680 cmp_rrdisp(code, src_op->base, dst_op->base, dst_op->disp, inst->extra.size);
1681 } else {
1682 cmp_irdisp(code, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size);
1683 }
1684 }
1685 passed = code->cur + 1;
1686 jcc(code, CC_LE, code->cur + 2);
1687 set_flag(opts, 0, FLAG_N);
1688 mov_ir(code, VECTOR_CHK, opts->gen.scratch2, SZ_D);
1689 mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D);
1690 jmp(code, opts->trap);
1691 *passed = code->cur - (passed+1);
1692 cycles(&opts->gen, 4);
1693 }
1694
1695 void translate_m68k_div(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1696 {
1697 code_info *code = &opts->gen.code;
1698 check_alloc_code(code, MAX_NATIVE_SIZE);
1699 //TODO: cycle exact division
1700 cycles(&opts->gen, inst->op == M68K_DIVS ? 158 : 140);
1701 set_flag(opts, 0, FLAG_C);
1702 push_r(code, RDX);
1703 push_r(code, RAX);
1704 if (dst_op->mode == MODE_REG_DIRECT) {
1705 mov_rr(code, dst_op->base, RAX, SZ_D);
1706 } else {
1707 mov_rdispr(code, dst_op->base, dst_op->disp, RAX, SZ_D);
1708 }
1709 if (src_op->mode == MODE_IMMED) {
1710 mov_ir(code, (src_op->disp & 0x8000) && inst->op == M68K_DIVS ? src_op->disp | 0xFFFF0000 : src_op->disp, opts->gen.scratch2, SZ_D);
1711 } else if (src_op->mode == MODE_REG_DIRECT) {
1712 if (inst->op == M68K_DIVS) {
1713 movsx_rr(code, src_op->base, opts->gen.scratch2, SZ_W, SZ_D);
1714 } else {
1715 movzx_rr(code, src_op->base, opts->gen.scratch2, SZ_W, SZ_D);
1716 }
1717 } else if (src_op->mode == MODE_REG_DISPLACE8) {
1718 if (inst->op == M68K_DIVS) {
1719 movsx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch2, SZ_W, SZ_D);
1720 } else {
1721 movzx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch2, SZ_W, SZ_D);
1722 }
1723 }
1724 cmp_ir(code, 0, opts->gen.scratch2, SZ_D);
1725 check_alloc_code(code, 6*MAX_INST_LEN);
1726 code_ptr not_zero = code->cur + 1;
1727 jcc(code, CC_NZ, code->cur + 2);
1728 pop_r(code, RAX);
1729 pop_r(code, RDX);
1730 mov_ir(code, VECTOR_INT_DIV_ZERO, opts->gen.scratch2, SZ_D);
1731 mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D);
1732 jmp(code, opts->trap);
1733 *not_zero = code->cur - (not_zero+1);
1734 if (inst->op == M68K_DIVS) {
1735 cdq(code);
1736 } else {
1737 xor_rr(code, RDX, RDX, SZ_D);
1738 }
1739 if (inst->op == M68K_DIVS) {
1740 idiv_r(code, opts->gen.scratch2, SZ_D);
1741 } else {
1742 div_r(code, opts->gen.scratch2, SZ_D);
1743 }
1744 code_ptr skip_sec_check, norm_off;
1745 if (inst->op == M68K_DIVS) {
1746 cmp_ir(code, 0x8000, RAX, SZ_D);
1747 skip_sec_check = code->cur + 1;
1748 jcc(code, CC_GE, code->cur + 2);
1749 cmp_ir(code, -0x8000, RAX, SZ_D);
1750 norm_off = code->cur + 1;
1751 jcc(code, CC_L, code->cur + 2);
1752 } else {
1753 cmp_ir(code, 0x10000, RAX, SZ_D);
1754 norm_off = code->cur + 1;
1755 jcc(code, CC_NC, code->cur + 2);
1756 }
1757 if (dst_op->mode == MODE_REG_DIRECT) {
1758 mov_rr(code, RDX, dst_op->base, SZ_W);
1759 shl_ir(code, 16, dst_op->base, SZ_D);
1760 mov_rr(code, RAX, dst_op->base, SZ_W);
1761 } else {
1762 mov_rrdisp(code, RDX, dst_op->base, dst_op->disp, SZ_W);
1763 shl_irdisp(code, 16, dst_op->base, dst_op->disp, SZ_D);
1764 mov_rrdisp(code, RAX, dst_op->base, dst_op->disp, SZ_W);
1765 }
1766 cmp_ir(code, 0, RAX, SZ_W);
1767 pop_r(code, RAX);
1768 pop_r(code, RDX);
1769 set_flag(opts, 0, FLAG_V);
1770 set_flag_cond(opts, CC_Z, FLAG_Z);
1771 set_flag_cond(opts, CC_S, FLAG_N);
1772 code_ptr end_off = code->cur + 1;
1773 jmp(code, code->cur + 2);
1774 *norm_off = code->cur - (norm_off + 1);
1775 if (inst->op == M68K_DIVS) {
1776 *skip_sec_check = code->cur - (skip_sec_check+1);
1777 }
1778 pop_r(code, RAX);
1779 pop_r(code, RDX);
1780 set_flag(opts, 1, FLAG_V);
1781 *end_off = code->cur - (end_off + 1);
1782 }
1783
1784 void translate_m68k_exg(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1785 {
1786 code_info *code = &opts->gen.code;
1787 cycles(&opts->gen, 6);
1788 if (dst_op->mode == MODE_REG_DIRECT) {
1789 mov_rr(code, dst_op->base, opts->gen.scratch2, SZ_D);
1790 if (src_op->mode == MODE_REG_DIRECT) {
1791 mov_rr(code, src_op->base, dst_op->base, SZ_D);
1792 mov_rr(code, opts->gen.scratch2, src_op->base, SZ_D);
1793 } else {
1794 mov_rdispr(code, src_op->base, src_op->disp, dst_op->base, SZ_D);
1795 mov_rrdisp(code, opts->gen.scratch2, src_op->base, src_op->disp, SZ_D);
1796 }
1797 } else {
1798 mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_D);
1799 if (src_op->mode == MODE_REG_DIRECT) {
1800 mov_rrdisp(code, src_op->base, dst_op->base, dst_op->disp, SZ_D);
1801 mov_rr(code, opts->gen.scratch2, src_op->base, SZ_D);
1802 } else {
1803 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_D);
1804 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_D);
1805 mov_rrdisp(code, opts->gen.scratch2, src_op->base, src_op->disp, SZ_D);
1806 }
1807 }
1808 }
1809
1810 void translate_m68k_mul(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1811 {
1812 code_info *code = &opts->gen.code;
1813 cycles(&opts->gen, 70); //TODO: Calculate the actual value based on the value of the <ea> parameter
1814 if (src_op->mode == MODE_IMMED) {
1815 mov_ir(code, inst->op == M68K_MULU ? (src_op->disp & 0xFFFF) : ((src_op->disp & 0x8000) ? src_op->disp | 0xFFFF0000 : src_op->disp), opts->gen.scratch1, SZ_D);
1816 } else if (src_op->mode == MODE_REG_DIRECT) {
1817 if (inst->op == M68K_MULS) {
1818 movsx_rr(code, src_op->base, opts->gen.scratch1, SZ_W, SZ_D);
1819 } else {
1820 movzx_rr(code, src_op->base, opts->gen.scratch1, SZ_W, SZ_D);
1821 }
1822 } else {
1823 if (inst->op == M68K_MULS) {
1824 movsx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W, SZ_D);
1825 } else {
1826 movzx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W, SZ_D);
1827 }
1828 }
1496 uint8_t dst_reg; 1829 uint8_t dst_reg;
1497 code_info *code = &opts->gen.code; 1830 if (dst_op->mode == MODE_REG_DIRECT) {
1498 check_cycles_int(&opts->gen, inst->address); 1831 dst_reg = dst_op->base;
1499 if (inst->op == M68K_MOVE) { 1832 if (inst->op == M68K_MULS) {
1500 return translate_m68k_move(opts, inst); 1833 movsx_rr(code, dst_reg, dst_reg, SZ_W, SZ_D);
1501 } else if(inst->op == M68K_LEA || inst->op == M68K_PEA) { 1834 } else {
1502 return translate_m68k_lea_pea(opts, inst); 1835 movzx_rr(code, dst_reg, dst_reg, SZ_W, SZ_D);
1503 } else if(inst->op == M68K_BSR) { 1836 }
1504 return translate_m68k_bsr(opts, inst); 1837 } else {
1505 } else if(inst->op == M68K_BCC) { 1838 dst_reg = opts->gen.scratch2;
1506 return translate_m68k_bcc(opts, inst); 1839 if (inst->op == M68K_MULS) {
1507 } else if(inst->op == M68K_JMP) { 1840 movsx_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_W, SZ_D);
1508 return translate_m68k_jmp_jsr(opts, inst); 1841 } else {
1509 } else if(inst->op == M68K_JSR) { 1842 movzx_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_W, SZ_D);
1510 return translate_m68k_jmp_jsr(opts, inst); 1843 }
1511 } else if(inst->op == M68K_RTS) { 1844 }
1512 return translate_m68k_rts(opts, inst); 1845 imul_rr(code, opts->gen.scratch1, dst_reg, SZ_D);
1513 } else if(inst->op == M68K_DBCC) { 1846 if (dst_op->mode == MODE_REG_DISPLACE8) {
1514 return translate_m68k_dbcc(opts, inst); 1847 mov_rrdisp(code, dst_reg, dst_op->base, dst_op->disp, SZ_D);
1515 } else if(inst->op == M68K_CLR) { 1848 }
1516 return translate_m68k_clr(opts, inst); 1849 cmp_ir(code, 0, dst_reg, SZ_D);
1517 } else if(inst->op == M68K_MOVEM) { 1850 update_flags(opts, N|Z|V0|C0);
1518 return translate_m68k_movem(opts, inst); 1851 }
1519 } else if(inst->op == M68K_LINK) { 1852
1520 return translate_m68k_link(opts, inst); 1853 void translate_m68k_negx(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1521 } else if(inst->op == M68K_UNLK) { 1854 {
1522 return translate_m68k_unlk(opts, inst); 1855 code_info *code = &opts->gen.code;
1523 } else if(inst->op == M68K_EXT) { 1856 cycles(&opts->gen, BUS);
1524 return translate_m68k_ext(opts, inst); 1857 if (dst_op->mode == MODE_REG_DIRECT) {
1525 } else if(inst->op == M68K_SCC) { 1858 if (dst_op->base == opts->gen.scratch1) {
1526 return translate_m68k_scc(opts, inst); 1859 push_r(code, opts->gen.scratch2);
1527 } else if(inst->op == M68K_MOVEP) { 1860 xor_rr(code, opts->gen.scratch2, opts->gen.scratch2, inst->extra.size);
1528 return translate_m68k_movep(opts, inst); 1861 flag_to_carry(opts, FLAG_X);
1529 } else if(inst->op == M68K_INVALID) { 1862 sbb_rr(code, dst_op->base, opts->gen.scratch2, inst->extra.size);
1530 if (inst->src.params.immed == 0x7100) { 1863 mov_rr(code, opts->gen.scratch2, dst_op->base, inst->extra.size);
1531 return retn(code); 1864 pop_r(code, opts->gen.scratch2);
1532 }
1533 mov_ir(code, inst->address, opts->gen.scratch1, SZ_D);
1534 return call(code, (code_ptr)m68k_invalid);
1535 } else if(inst->op == M68K_CMP) {
1536 return translate_m68k_cmp(opts, inst);
1537 }
1538 x86_ea src_op, dst_op;
1539 if (inst->src.addr_mode != MODE_UNUSED) {
1540 translate_m68k_op(inst, &src_op, opts, 0);
1541 }
1542 if (inst->dst.addr_mode != MODE_UNUSED) {
1543 translate_m68k_op(inst, &dst_op, opts, 1);
1544 }
1545 uint8_t size;
1546 switch(inst->op)
1547 {
1548 case M68K_ABCD:
1549 case M68K_SBCD:
1550 if (src_op.base != opts->gen.scratch2) {
1551 if (src_op.mode == MODE_REG_DIRECT) {
1552 mov_rr(code, src_op.base, opts->gen.scratch2, SZ_B);
1553 } else {
1554 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, SZ_B);
1555 }
1556 }
1557 if (dst_op.base != opts->gen.scratch1) {
1558 if (dst_op.mode == MODE_REG_DIRECT) {
1559 mov_rr(code, dst_op.base, opts->gen.scratch1, SZ_B);
1560 } else {
1561 mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1562 }
1563 }
1564 flag_to_carry(opts, FLAG_X);
1565 jcc(code, CC_NC, code->cur + 5);
1566 if (inst->op == M68K_ABCD) {
1567 add_ir(code, 1, opts->gen.scratch1, SZ_B);
1568 } else {
1569 sub_ir(code, 1, opts->gen.scratch1, SZ_B);
1570 }
1571 call(code, (code_ptr) (inst->op == M68K_ABCD ? bcd_add : bcd_sub));
1572 reg_to_flag(opts, CH, FLAG_C);
1573 reg_to_flag(opts, CH, FLAG_X);
1574 cmp_ir(code, 0, opts->gen.scratch1, SZ_B);
1575 jcc(code, CC_Z, code->cur + 4);
1576 set_flag(opts, 0, FLAG_Z);
1577 if (dst_op.base != opts->gen.scratch1) {
1578 if (dst_op.mode == MODE_REG_DIRECT) {
1579 mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_B);
1580 } else {
1581 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B);
1582 }
1583 }
1584 m68k_save_result(inst, opts);
1585 break;
1586 case M68K_ADD:
1587 case M68K_SUB:
1588 translate_m68k_arith(opts, inst, X|N|Z|V|C, &src_op, &dst_op);
1589 break;
1590 case M68K_ADDX:
1591 case M68K_SUBX:
1592 //z flag is special cased in translate_m68k_arith
1593 translate_m68k_arith(opts, inst, X|N|V|C, &src_op, &dst_op);
1594 break;
1595 case M68K_AND:
1596 case M68K_EOR:
1597 case M68K_OR:
1598 translate_m68k_arith(opts, inst, N|Z|V0|C0, &src_op, &dst_op);
1599 break;
1600 case M68K_ANDI_CCR:
1601 case M68K_ANDI_SR: {
1602 cycles(&opts->gen, 20);
1603 //TODO: If ANDI to SR, trap if not in supervisor mode
1604 uint32_t flag_mask = 0;
1605 if (!(inst->src.params.immed & 0x1)) {
1606 flag_mask |= C0;
1607 }
1608 if (!(inst->src.params.immed & 0x2)) {
1609 flag_mask |= V0;
1610 }
1611 if (!(inst->src.params.immed & 0x4)) {
1612 flag_mask |= Z0;
1613 }
1614 if (!(inst->src.params.immed & 0x8)) {
1615 flag_mask |= N0;
1616 }
1617 if (!(inst->src.params.immed & 0x10)) {
1618 flag_mask |= X0;
1619 }
1620 update_flags(opts, flag_mask);
1621 if (inst->op == M68K_ANDI_SR) {
1622 and_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
1623 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) {
1624 //leave supervisor mode
1625 swap_ssp_usp(opts);
1626 }
1627 if (inst->src.params.immed & 0x700) {
1628 call(code, opts->do_sync);
1629 }
1630 }
1631 break;
1632 }
1633 case M68K_ASL:
1634 case M68K_LSL:
1635 translate_shift(opts, inst, &src_op, &dst_op, shl_ir, shl_irdisp, shl_clr, shl_clrdisp, shr_ir, shr_irdisp);
1636 break;
1637 case M68K_ASR:
1638 translate_shift(opts, inst, &src_op, &dst_op, sar_ir, sar_irdisp, sar_clr, sar_clrdisp, NULL, NULL);
1639 break;
1640 case M68K_LSR:
1641 translate_shift(opts, inst, &src_op, &dst_op, shr_ir, shr_irdisp, shr_clr, shr_clrdisp, shl_ir, shl_irdisp);
1642 break;
1643 case M68K_BCHG:
1644 case M68K_BCLR:
1645 case M68K_BSET:
1646 case M68K_BTST:
1647 cycles(&opts->gen, inst->extra.size == OPSIZE_BYTE ? 4 : (
1648 inst->op == M68K_BTST ? 6 : (inst->op == M68K_BCLR ? 10 : 8))
1649 );
1650 if (src_op.mode == MODE_IMMED) {
1651 if (inst->extra.size == OPSIZE_BYTE) {
1652 src_op.disp &= 0x7;
1653 }
1654 if (dst_op.mode == MODE_REG_DIRECT) {
1655 op_ir(code, inst, src_op.disp, dst_op.base, inst->extra.size);
1656 } else {
1657 op_irdisp(code, inst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
1658 }
1659 } else {
1660 if (src_op.mode == MODE_REG_DISPLACE8 || (inst->dst.addr_mode != MODE_REG && src_op.base != opts->gen.scratch1 && src_op.base != opts->gen.scratch2)) {
1661 if (dst_op.base == opts->gen.scratch1) {
1662 push_r(code, opts->gen.scratch2);
1663 if (src_op.mode == MODE_REG_DIRECT) {
1664 mov_rr(code, src_op.base, opts->gen.scratch2, SZ_B);
1665 } else {
1666 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, SZ_B);
1667 }
1668 src_op.base = opts->gen.scratch2;
1669 } else {
1670 if (src_op.mode == MODE_REG_DIRECT) {
1671 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_B);
1672 } else {
1673 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B);
1674 }
1675 src_op.base = opts->gen.scratch1;
1676 }
1677 }
1678 uint8_t size = inst->extra.size;
1679 if (dst_op.mode == MODE_REG_DISPLACE8) {
1680 if (src_op.base != opts->gen.scratch1 && src_op.base != opts->gen.scratch2) {
1681 if (src_op.mode == MODE_REG_DIRECT) {
1682 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_D);
1683 } else {
1684 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_D);
1685 src_op.mode = MODE_REG_DIRECT;
1686 }
1687 src_op.base = opts->gen.scratch1;
1688 }
1689 //b### with register destination is modulo 32
1690 //x86 with a memory destination isn't modulo anything
1691 //so use an and here to force the value to be modulo 32
1692 and_ir(code, 31, opts->gen.scratch1, SZ_D);
1693 } else if(inst->dst.addr_mode != MODE_REG) {
1694 //b### with memory destination is modulo 8
1695 //x86-64 doesn't support 8-bit bit operations
1696 //so we fake it by forcing the bit number to be modulo 8
1697 and_ir(code, 7, src_op.base, SZ_D);
1698 size = SZ_D;
1699 }
1700 if (dst_op.mode == MODE_REG_DIRECT) {
1701 op_rr(code, inst, src_op.base, dst_op.base, size);
1702 } else {
1703 op_rrdisp(code, inst, src_op.base, dst_op.base, dst_op.disp, size);
1704 }
1705 if (src_op.base == opts->gen.scratch2) {
1706 pop_r(code, opts->gen.scratch2);
1707 }
1708 }
1709 //x86 sets the carry flag to the value of the bit tested
1710 //68K sets the zero flag to the complement of the bit tested
1711 set_flag_cond(opts, CC_NC, FLAG_Z);
1712 if (inst->op != M68K_BTST) {
1713 m68k_save_result(inst, opts);
1714 }
1715 break;
1716 case M68K_CHK:
1717 {
1718 cycles(&opts->gen, 6);
1719 if (dst_op.mode == MODE_REG_DIRECT) {
1720 cmp_ir(code, 0, dst_op.base, inst->extra.size);
1721 } else {
1722 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size);
1723 }
1724 uint32_t isize;
1725 switch(inst->src.addr_mode)
1726 {
1727 case MODE_AREG_DISPLACE:
1728 case MODE_AREG_INDEX_DISP8:
1729 case MODE_ABSOLUTE_SHORT:
1730 case MODE_PC_INDEX_DISP8:
1731 case MODE_PC_DISPLACE:
1732 case MODE_IMMEDIATE:
1733 isize = 4;
1734 break;
1735 case MODE_ABSOLUTE:
1736 isize = 6;
1737 break;
1738 default:
1739 isize = 2;
1740 }
1741 //make sure we won't start a new chunk in the middle of these branches
1742 check_alloc_code(code, MAX_INST_LEN * 11);
1743 code_ptr passed = code->cur + 1;
1744 jcc(code, CC_GE, code->cur + 2);
1745 set_flag(opts, 1, FLAG_N);
1746 mov_ir(code, VECTOR_CHK, opts->gen.scratch2, SZ_D);
1747 mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D);
1748 jmp(code, opts->trap);
1749 *passed = code->cur - (passed+1);
1750 if (dst_op.mode == MODE_REG_DIRECT) {
1751 if (src_op.mode == MODE_REG_DIRECT) {
1752 cmp_rr(code, src_op.base, dst_op.base, inst->extra.size);
1753 } else if(src_op.mode == MODE_REG_DISPLACE8) {
1754 cmp_rdispr(code, src_op.base, src_op.disp, dst_op.base, inst->extra.size);
1755 } else {
1756 cmp_ir(code, src_op.disp, dst_op.base, inst->extra.size);
1757 }
1758 } else if(dst_op.mode == MODE_REG_DISPLACE8) {
1759 if (src_op.mode == MODE_REG_DIRECT) {
1760 cmp_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, inst->extra.size);
1761 } else {
1762 cmp_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
1763 }
1764 }
1765 passed = code->cur + 1;
1766 jcc(code, CC_LE, code->cur + 2);
1767 set_flag(opts, 0, FLAG_N);
1768 mov_ir(code, VECTOR_CHK, opts->gen.scratch2, SZ_D);
1769 mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D);
1770 jmp(code, opts->trap);
1771 *passed = code->cur - (passed+1);
1772 cycles(&opts->gen, 4);
1773 break;
1774 }
1775 case M68K_DIVS:
1776 case M68K_DIVU:
1777 {
1778 check_alloc_code(code, MAX_NATIVE_SIZE);
1779 //TODO: cycle exact division
1780 cycles(&opts->gen, inst->op == M68K_DIVS ? 158 : 140);
1781 set_flag(opts, 0, FLAG_C);
1782 push_r(code, RDX);
1783 push_r(code, RAX);
1784 if (dst_op.mode == MODE_REG_DIRECT) {
1785 mov_rr(code, dst_op.base, RAX, SZ_D);
1786 } else {
1787 mov_rdispr(code, dst_op.base, dst_op.disp, RAX, SZ_D);
1788 }
1789 if (src_op.mode == MODE_IMMED) {
1790 mov_ir(code, (src_op.disp & 0x8000) && inst->op == M68K_DIVS ? src_op.disp | 0xFFFF0000 : src_op.disp, opts->gen.scratch2, SZ_D);
1791 } else if (src_op.mode == MODE_REG_DIRECT) {
1792 if (inst->op == M68K_DIVS) {
1793 movsx_rr(code, src_op.base, opts->gen.scratch2, SZ_W, SZ_D);
1794 } else {
1795 movzx_rr(code, src_op.base, opts->gen.scratch2, SZ_W, SZ_D);
1796 }
1797 } else if (src_op.mode == MODE_REG_DISPLACE8) {
1798 if (inst->op == M68K_DIVS) {
1799 movsx_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, SZ_W, SZ_D);
1800 } else {
1801 movzx_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, SZ_W, SZ_D);
1802 }
1803 }
1804 cmp_ir(code, 0, opts->gen.scratch2, SZ_D);
1805 check_alloc_code(code, 6*MAX_INST_LEN);
1806 code_ptr not_zero = code->cur + 1;
1807 jcc(code, CC_NZ, code->cur + 2);
1808 pop_r(code, RAX);
1809 pop_r(code, RDX);
1810 mov_ir(code, VECTOR_INT_DIV_ZERO, opts->gen.scratch2, SZ_D);
1811 mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D);
1812 jmp(code, opts->trap);
1813 *not_zero = code->cur - (not_zero+1);
1814 if (inst->op == M68K_DIVS) {
1815 cdq(code);
1816 } else {
1817 xor_rr(code, RDX, RDX, SZ_D);
1818 }
1819 if (inst->op == M68K_DIVS) {
1820 idiv_r(code, opts->gen.scratch2, SZ_D);
1821 } else {
1822 div_r(code, opts->gen.scratch2, SZ_D);
1823 }
1824 code_ptr skip_sec_check;
1825 if (inst->op == M68K_DIVS) {
1826 cmp_ir(code, 0x8000, RAX, SZ_D);
1827 skip_sec_check = code->cur + 1;
1828 jcc(code, CC_GE, code->cur + 2);
1829 cmp_ir(code, -0x8000, RAX, SZ_D);
1830 norm_off = code->cur + 1;
1831 jcc(code, CC_L, code->cur + 2);
1832 } else {
1833 cmp_ir(code, 0x10000, RAX, SZ_D);
1834 norm_off = code->cur + 1;
1835 jcc(code, CC_NC, code->cur + 2);
1836 }
1837 if (dst_op.mode == MODE_REG_DIRECT) {
1838 mov_rr(code, RDX, dst_op.base, SZ_W);
1839 shl_ir(code, 16, dst_op.base, SZ_D);
1840 mov_rr(code, RAX, dst_op.base, SZ_W);
1841 } else {
1842 mov_rrdisp(code, RDX, dst_op.base, dst_op.disp, SZ_W);
1843 shl_irdisp(code, 16, dst_op.base, dst_op.disp, SZ_D);
1844 mov_rrdisp(code, RAX, dst_op.base, dst_op.disp, SZ_W);
1845 }
1846 cmp_ir(code, 0, RAX, SZ_W);
1847 pop_r(code, RAX);
1848 pop_r(code, RDX);
1849 set_flag(opts, 0, FLAG_V);
1850 set_flag_cond(opts, CC_Z, FLAG_Z);
1851 set_flag_cond(opts, CC_S, FLAG_N);
1852 end_off = code->cur + 1;
1853 jmp(code, code->cur + 2);
1854 *norm_off = code->cur - (norm_off + 1);
1855 if (inst->op == M68K_DIVS) {
1856 *skip_sec_check = code->cur - (skip_sec_check+1);
1857 }
1858 pop_r(code, RAX);
1859 pop_r(code, RDX);
1860 set_flag(opts, 1, FLAG_V);
1861 *end_off = code->cur - (end_off + 1);
1862 break;
1863 }
1864 case M68K_EORI_CCR:
1865 case M68K_EORI_SR:
1866 cycles(&opts->gen, 20);
1867 //TODO: If ANDI to SR, trap if not in supervisor mode
1868 if (inst->src.params.immed & 0x1) {
1869 xor_flag(opts, 1, FLAG_C);
1870 }
1871 if (inst->src.params.immed & 0x2) {
1872 xor_flag(opts, 1, FLAG_V);
1873 }
1874 if (inst->src.params.immed & 0x4) {
1875 xor_flag(opts, 1, FLAG_Z);
1876 }
1877 if (inst->src.params.immed & 0x8) {
1878 xor_flag(opts, 1, FLAG_N);
1879 }
1880 if (inst->src.params.immed & 0x10) {
1881 xor_flag(opts, 1, FLAG_X);
1882 }
1883 if (inst->op == M68K_ORI_SR) {
1884 xor_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
1885 if (inst->src.params.immed & 0x700) {
1886 call(code, opts->do_sync);
1887 }
1888 }
1889 break;
1890 case M68K_EXG:
1891 cycles(&opts->gen, 6);
1892 if (dst_op.mode == MODE_REG_DIRECT) {
1893 mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_D);
1894 if (src_op.mode == MODE_REG_DIRECT) {
1895 mov_rr(code, src_op.base, dst_op.base, SZ_D);
1896 mov_rr(code, opts->gen.scratch2, src_op.base, SZ_D);
1897 } else {
1898 mov_rdispr(code, src_op.base, src_op.disp, dst_op.base, SZ_D);
1899 mov_rrdisp(code, opts->gen.scratch2, src_op.base, src_op.disp, SZ_D);
1900 }
1901 } else {
1902 mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_D);
1903 if (src_op.mode == MODE_REG_DIRECT) {
1904 mov_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, SZ_D);
1905 mov_rr(code, opts->gen.scratch2, src_op.base, SZ_D);
1906 } else {
1907 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_D);
1908 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_D);
1909 mov_rrdisp(code, opts->gen.scratch2, src_op.base, src_op.disp, SZ_D);
1910 }
1911 }
1912 break;
1913 case M68K_ILLEGAL:
1914 call(code, opts->gen.save_context);
1915 #ifdef X86_64
1916 mov_rr(code, opts->gen.context_reg, RDI, SZ_PTR);
1917 #else
1918 push_r(code, opts->gen.context_reg);
1919 #endif
1920 call(code, (code_ptr)print_regs_exit);
1921 break;
1922 case M68K_MOVE_FROM_SR:
1923 //TODO: Trap if not in system mode
1924 call(code, opts->get_sr);
1925 if (dst_op.mode == MODE_REG_DIRECT) {
1926 mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_W);
1927 } else {
1928 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_W);
1929 }
1930 m68k_save_result(inst, opts);
1931 break;
1932 case M68K_MOVE_CCR:
1933 case M68K_MOVE_SR:
1934 //TODO: Privilege check for MOVE to SR
1935 if (src_op.mode == MODE_IMMED) {
1936 uint32_t flag_mask = src_op.disp & 0x10 ? X1 : X0;
1937 flag_mask |= src_op.disp & 0x8 ? N1 : N0;
1938 flag_mask |= src_op.disp & 0x4 ? Z1 : Z0;
1939 flag_mask |= src_op.disp & 0x2 ? V1 : V0;
1940 flag_mask |= src_op.disp & 0x1 ? C1 : C0;
1941 update_flags(opts, flag_mask);
1942 if (inst->op == M68K_MOVE_SR) {
1943 mov_irdisp(code, (src_op.disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
1944 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) {
1945 //leave supervisor mode
1946 mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D);
1947 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D);
1948 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D);
1949 }
1950 call(code, opts->do_sync);
1951 }
1952 cycles(&opts->gen, 12);
1953 } else {
1954 if (src_op.base != opts->gen.scratch1) {
1955 if (src_op.mode == MODE_REG_DIRECT) {
1956 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_W);
1957 } else {
1958 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_W);
1959 }
1960 }
1961 call(code, inst->op == M68K_MOVE_SR ? opts->set_sr : opts->set_ccr);
1962 cycles(&opts->gen, 12);
1963
1964 }
1965 break;
1966 case M68K_MOVE_USP:
1967 cycles(&opts->gen, BUS);
1968 //TODO: Trap if not in supervisor mode
1969 //bt_irdisp(code, BIT_SUPERVISOR, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
1970 if (inst->src.addr_mode == MODE_UNUSED) {
1971 areg_to_native(opts, 8, dst_op.mode == MODE_REG_DIRECT ? dst_op.base : opts->gen.scratch1);
1972 if (dst_op.mode != MODE_REG_DIRECT) {
1973 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_D);
1974 }
1975 } else {
1976 if (src_op.mode != MODE_REG_DIRECT) {
1977 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_D);
1978 src_op.base = opts->gen.scratch1;
1979 }
1980 native_to_areg(opts, src_op.base, 8);
1981 }
1982 break;
1983 //case M68K_MOVEP:
1984 case M68K_MULS:
1985 case M68K_MULU:
1986 cycles(&opts->gen, 70); //TODO: Calculate the actual value based on the value of the <ea> parameter
1987 if (src_op.mode == MODE_IMMED) {
1988 mov_ir(code, inst->op == M68K_MULU ? (src_op.disp & 0xFFFF) : ((src_op.disp & 0x8000) ? src_op.disp | 0xFFFF0000 : src_op.disp), opts->gen.scratch1, SZ_D);
1989 } else if (src_op.mode == MODE_REG_DIRECT) {
1990 if (inst->op == M68K_MULS) {
1991 movsx_rr(code, src_op.base, opts->gen.scratch1, SZ_W, SZ_D);
1992 } else {
1993 movzx_rr(code, src_op.base, opts->gen.scratch1, SZ_W, SZ_D);
1994 }
1995 } else {
1996 if (inst->op == M68K_MULS) {
1997 movsx_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_W, SZ_D);
1998 } else {
1999 movzx_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_W, SZ_D);
2000 }
2001 }
2002 if (dst_op.mode == MODE_REG_DIRECT) {
2003 dst_reg = dst_op.base;
2004 if (inst->op == M68K_MULS) {
2005 movsx_rr(code, dst_reg, dst_reg, SZ_W, SZ_D);
2006 } else {
2007 movzx_rr(code, dst_reg, dst_reg, SZ_W, SZ_D);
2008 }
2009 } else {
2010 dst_reg = opts->gen.scratch2;
2011 if (inst->op == M68K_MULS) {
2012 movsx_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_W, SZ_D);
2013 } else {
2014 movzx_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_W, SZ_D);
2015 }
2016 }
2017 imul_rr(code, opts->gen.scratch1, dst_reg, SZ_D);
2018 if (dst_op.mode == MODE_REG_DISPLACE8) {
2019 mov_rrdisp(code, dst_reg, dst_op.base, dst_op.disp, SZ_D);
2020 }
2021 cmp_ir(code, 0, dst_reg, SZ_D);
2022 update_flags(opts, N|Z|V0|C0);
2023 break;
2024 //case M68K_NBCD:
2025 case M68K_NEG:
2026 translate_m68k_unary(opts, inst, X|N|Z|V|C, &dst_op);
2027 break;
2028 case M68K_NEGX: {
2029 cycles(&opts->gen, BUS);
2030 if (dst_op.mode == MODE_REG_DIRECT) {
2031 if (dst_op.base == opts->gen.scratch1) {
2032 push_r(code, opts->gen.scratch2);
2033 xor_rr(code, opts->gen.scratch2, opts->gen.scratch2, inst->extra.size);
2034 flag_to_carry(opts, FLAG_X);
2035 sbb_rr(code, dst_op.base, opts->gen.scratch2, inst->extra.size);
2036 mov_rr(code, opts->gen.scratch2, dst_op.base, inst->extra.size);
2037 pop_r(code, opts->gen.scratch2);
2038 } else {
2039 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, inst->extra.size);
2040 flag_to_carry(opts, FLAG_X);
2041 sbb_rr(code, dst_op.base, opts->gen.scratch1, inst->extra.size);
2042 mov_rr(code, opts->gen.scratch1, dst_op.base, inst->extra.size);
2043 }
2044 } else { 1865 } else {
2045 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, inst->extra.size); 1866 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, inst->extra.size);
2046 flag_to_carry(opts, FLAG_X); 1867 flag_to_carry(opts, FLAG_X);
2047 sbb_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, inst->extra.size); 1868 sbb_rr(code, dst_op->base, opts->gen.scratch1, inst->extra.size);
2048 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, inst->extra.size); 1869 mov_rr(code, opts->gen.scratch1, dst_op->base, inst->extra.size);
2049 } 1870 }
2050 set_flag_cond(opts, CC_C, FLAG_C); 1871 } else {
2051 code_ptr after_flag_set = code->cur + 1; 1872 xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, inst->extra.size);
2052 jcc(code, CC_Z, code->cur + 2); 1873 flag_to_carry(opts, FLAG_X);
2053 set_flag(opts, 0, FLAG_Z); 1874 sbb_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch1, inst->extra.size);
2054 *after_flag_set = code->cur - (after_flag_set+1); 1875 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, inst->extra.size);
2055 set_flag_cond(opts, CC_S, FLAG_N); 1876 }
2056 set_flag_cond(opts, CC_O, FLAG_V); 1877 set_flag_cond(opts, CC_C, FLAG_C);
2057 if (opts->flag_regs[FLAG_C] >= 0) { 1878 code_ptr after_flag_set = code->cur + 1;
2058 flag_to_flag(opts, FLAG_C, FLAG_X); 1879 jcc(code, CC_Z, code->cur + 2);
2059 } else { 1880 set_flag(opts, 0, FLAG_Z);
2060 set_flag_cond(opts, CC_C, FLAG_X); 1881 *after_flag_set = code->cur - (after_flag_set+1);
2061 } 1882 set_flag_cond(opts, CC_S, FLAG_N);
1883 set_flag_cond(opts, CC_O, FLAG_V);
1884 if (opts->flag_regs[FLAG_C] >= 0) {
1885 flag_to_flag(opts, FLAG_C, FLAG_X);
1886 } else {
1887 set_flag_cond(opts, CC_C, FLAG_X);
1888 }
1889 m68k_save_result(inst, opts);
1890 }
1891
1892 void translate_m68k_rot(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1893 {
1894 code_info *code = &opts->gen.code;
1895 int32_t init_flags = C|V0;
1896 if (inst->src.addr_mode == MODE_UNUSED) {
1897 cycles(&opts->gen, BUS);
1898 //Memory rotate
1899 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
1900 flag_to_carry(opts, FLAG_X);
1901 init_flags |= X;
1902 }
1903 op_ir(code, inst, 1, dst_op->base, inst->extra.size);
1904 update_flags(opts, init_flags);
1905 cmp_ir(code, 0, dst_op->base, inst->extra.size);
1906 update_flags(opts, Z|N);
2062 m68k_save_result(inst, opts); 1907 m68k_save_result(inst, opts);
2063 break; 1908 } else {
2064 } 1909 if (src_op->mode == MODE_IMMED) {
2065 case M68K_NOP: 1910 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op->disp*2);
2066 cycles(&opts->gen, BUS);
2067 break;
2068 case M68K_NOT:
2069 translate_m68k_unary(opts, inst, N|Z|V0|C0, &dst_op);
2070 break;
2071 case M68K_ORI_CCR:
2072 case M68K_ORI_SR:
2073 cycles(&opts->gen, 20);
2074 //TODO: If ORI to SR, trap if not in supervisor mode
2075 uint32_t flag_mask = 0;
2076 if (inst->src.params.immed & 0x1) {
2077 flag_mask |= C1;
2078 }
2079 if (inst->src.params.immed & 0x2) {
2080 flag_mask |= V1;
2081 }
2082 if (inst->src.params.immed & 0x4) {
2083 flag_mask |= Z1;
2084 }
2085 if (inst->src.params.immed & 0x8) {
2086 flag_mask |= N1;
2087 }
2088 if (inst->src.params.immed & 0x10) {
2089 flag_mask |= X1;
2090 }
2091 update_flags(opts, flag_mask);
2092 if (inst->op == M68K_ORI_SR) {
2093 or_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2094 if (inst->src.params.immed & 0x700) {
2095 call(code, opts->do_sync);
2096 }
2097 }
2098 break;
2099 case M68K_RESET:
2100 call(code, opts->gen.save_context);
2101 #ifdef X86_64
2102 mov_rr(code, opts->gen.context_reg, RDI, SZ_PTR);
2103 #else
2104 push_r(code, opts->gen.context_reg);
2105 #endif
2106 call(code, (code_ptr)print_regs_exit);
2107 break;
2108 case M68K_ROL:
2109 case M68K_ROR:
2110 case M68K_ROXL:
2111 case M68K_ROXR: {
2112 int32_t init_flags = C|V0;
2113 if (inst->src.addr_mode == MODE_UNUSED) {
2114 cycles(&opts->gen, BUS);
2115 //Memory rotate
2116 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) { 1911 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2117 flag_to_carry(opts, FLAG_X); 1912 flag_to_carry(opts, FLAG_X);
2118 init_flags |= X; 1913 init_flags |= X;
2119 } 1914 }
2120 op_ir(code, inst, 1, dst_op.base, inst->extra.size); 1915 if (dst_op->mode == MODE_REG_DIRECT) {
1916 op_ir(code, inst, src_op->disp, dst_op->base, inst->extra.size);
1917 } else {
1918 op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size);
1919 }
2121 update_flags(opts, init_flags); 1920 update_flags(opts, init_flags);
2122 cmp_ir(code, 0, dst_op.base, inst->extra.size); 1921 } else {
2123 update_flags(opts, Z|N); 1922 if (src_op->mode == MODE_REG_DIRECT) {
2124 m68k_save_result(inst, opts); 1923 if (src_op->base != opts->gen.scratch1) {
2125 } else { 1924 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_B);
2126 if (src_op.mode == MODE_IMMED) {
2127 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2);
2128 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2129 flag_to_carry(opts, FLAG_X);
2130 init_flags |= X;
2131 } 1925 }
2132 if (dst_op.mode == MODE_REG_DIRECT) {
2133 op_ir(code, inst, src_op.disp, dst_op.base, inst->extra.size);
2134 } else {
2135 op_irdisp(code, inst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
2136 }
2137 update_flags(opts, init_flags);
2138 } else { 1926 } else {
2139 if (src_op.mode == MODE_REG_DIRECT) { 1927 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_B);
2140 if (src_op.base != opts->gen.scratch1) { 1928 }
2141 mov_rr(code, src_op.base, opts->gen.scratch1, SZ_B); 1929 and_ir(code, 63, opts->gen.scratch1, SZ_D);
2142 } 1930 code_ptr zero_off = code->cur + 1;
2143 } else { 1931 jcc(code, CC_Z, code->cur + 2);
2144 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B); 1932 add_rr(code, opts->gen.scratch1, CYCLES, SZ_D);
2145 } 1933 add_rr(code, opts->gen.scratch1, CYCLES, SZ_D);
2146 and_ir(code, 63, opts->gen.scratch1, SZ_D); 1934 cmp_ir(code, 32, opts->gen.scratch1, SZ_B);
2147 zero_off = code->cur + 1; 1935 code_ptr norm_off = code->cur + 1;
2148 jcc(code, CC_Z, code->cur + 2); 1936 jcc(code, CC_L, code->cur + 2);
2149 add_rr(code, opts->gen.scratch1, CYCLES, SZ_D); 1937 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2150 add_rr(code, opts->gen.scratch1, CYCLES, SZ_D); 1938 flag_to_carry(opts, FLAG_X);
2151 cmp_ir(code, 32, opts->gen.scratch1, SZ_B); 1939 init_flags |= X;
2152 norm_off = code->cur + 1;
2153 jcc(code, CC_L, code->cur + 2);
2154 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2155 flag_to_carry(opts, FLAG_X);
2156 init_flags |= X;
2157 } else {
2158 sub_ir(code, 32, opts->gen.scratch1, SZ_B);
2159 }
2160 if (dst_op.mode == MODE_REG_DIRECT) {
2161 op_ir(code, inst, 31, dst_op.base, inst->extra.size);
2162 op_ir(code, inst, 1, dst_op.base, inst->extra.size);
2163 } else {
2164 op_irdisp(code, inst, 31, dst_op.base, dst_op.disp, inst->extra.size);
2165 op_irdisp(code, inst, 1, dst_op.base, dst_op.disp, inst->extra.size);
2166 }
2167
2168 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2169 set_flag_cond(opts, CC_C, FLAG_X);
2170 sub_ir(code, 32, opts->gen.scratch1, SZ_B);
2171 *norm_off = code->cur - (norm_off+1);
2172 flag_to_carry(opts, FLAG_X);
2173 } else {
2174 *norm_off = code->cur - (norm_off+1);
2175 }
2176 if (dst_op.mode == MODE_REG_DIRECT) {
2177 op_r(code, inst, dst_op.base, inst->extra.size);
2178 } else {
2179 op_rdisp(code, inst, dst_op.base, dst_op.disp, inst->extra.size);
2180 }
2181 update_flags(opts, init_flags);
2182 end_off = code->cur + 1;
2183 jmp(code, code->cur + 2);
2184 *zero_off = code->cur - (zero_off+1);
2185 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2186 //Carry flag is set to X flag when count is 0, this is different from ROR/ROL
2187 flag_to_flag(opts, FLAG_X, FLAG_C);
2188 } else {
2189 set_flag(opts, 0, FLAG_C);
2190 }
2191 *end_off = code->cur - (end_off+1);
2192 }
2193 if (dst_op.mode == MODE_REG_DIRECT) {
2194 cmp_ir(code, 0, dst_op.base, inst->extra.size);
2195 } else { 1940 } else {
2196 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size); 1941 sub_ir(code, 32, opts->gen.scratch1, SZ_B);
2197 } 1942 }
2198 update_flags(opts, Z|N); 1943 if (dst_op->mode == MODE_REG_DIRECT) {
2199 } 1944 op_ir(code, inst, 31, dst_op->base, inst->extra.size);
2200 break; 1945 op_ir(code, inst, 1, dst_op->base, inst->extra.size);
2201 } 1946 } else {
2202 case M68K_RTE: 1947 op_irdisp(code, inst, 31, dst_op->base, dst_op->disp, inst->extra.size);
2203 //TODO: Trap if not in system mode 1948 op_irdisp(code, inst, 1, dst_op->base, dst_op->disp, inst->extra.size);
2204 //Read saved SR 1949 }
2205 areg_to_native(opts, 7, opts->gen.scratch1); 1950
2206 call(code, opts->read_16); 1951 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2207 addi_areg(opts, 2, 7); 1952 set_flag_cond(opts, CC_C, FLAG_X);
2208 call(code, opts->set_sr); 1953 sub_ir(code, 32, opts->gen.scratch1, SZ_B);
2209 //Read saved PC 1954 *norm_off = code->cur - (norm_off+1);
2210 areg_to_native(opts, 7, opts->gen.scratch1); 1955 flag_to_carry(opts, FLAG_X);
2211 call(code, opts->read_32); 1956 } else {
2212 addi_areg(opts, 4, 7); 1957 *norm_off = code->cur - (norm_off+1);
2213 //Check if we've switched to user mode and swap stack pointers if needed 1958 }
2214 bt_irdisp(code, 5, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); 1959 if (dst_op->mode == MODE_REG_DIRECT) {
2215 end_off = code->cur + 1; 1960 op_r(code, inst, dst_op->base, inst->extra.size);
2216 jcc(code, CC_C, code->cur + 2); 1961 } else {
2217 swap_ssp_usp(opts); 1962 op_rdisp(code, inst, dst_op->base, dst_op->disp, inst->extra.size);
2218 *end_off = code->cur - (end_off+1); 1963 }
2219 //Get native address, sync components, recalculate integer points and jump to returned address 1964 update_flags(opts, init_flags);
2220 call(code, opts->native_addr_and_sync); 1965 code_ptr end_off = code->cur + 1;
2221 jmp_r(code, opts->gen.scratch1); 1966 jmp(code, code->cur + 2);
2222 break; 1967 *zero_off = code->cur - (zero_off+1);
2223 case M68K_RTR: 1968 if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2224 translate_m68k_rtr(opts, inst); 1969 //Carry flag is set to X flag when count is 0, this is different from ROR/ROL
2225 break; 1970 flag_to_flag(opts, FLAG_X, FLAG_C);
2226 case M68K_STOP: { 1971 } else {
2227 //TODO: Trap if not in system mode 1972 set_flag(opts, 0, FLAG_C);
2228 //manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction 1973 }
2229 //possibly even 12 since that's how long MOVE to SR takes 1974 *end_off = code->cur - (end_off+1);
2230 cycles(&opts->gen, BUS*2); 1975 }
2231 uint32_t flag_mask = src_op.disp & 0x10 ? X1 : X0; 1976 if (dst_op->mode == MODE_REG_DIRECT) {
2232 flag_mask |= src_op.disp & 0x8 ? N1 : N0; 1977 cmp_ir(code, 0, dst_op->base, inst->extra.size);
2233 flag_mask |= src_op.disp & 0x4 ? Z1 : Z0; 1978 } else {
2234 flag_mask |= src_op.disp & 0x2 ? V1 : V0; 1979 cmp_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size);
2235 flag_mask |= src_op.disp & 0x1 ? C1 : C0; 1980 }
2236 update_flags(opts, flag_mask); 1981 update_flags(opts, Z|N);
2237 mov_irdisp(code, (src_op.disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); 1982 }
1983 }
1984
1985 void translate_m68k_illegal(m68k_options *opts, m68kinst *inst)
1986 {
1987 code_info *code = &opts->gen.code;
1988 call(code, opts->gen.save_context);
1989 #ifdef X86_64
1990 mov_rr(code, opts->gen.context_reg, RDI, SZ_PTR);
1991 #else
1992 push_r(code, opts->gen.context_reg);
1993 #endif
1994 call(code, (code_ptr)print_regs_exit);
1995 }
1996
1997 #define BIT_SUPERVISOR 5
1998
1999 void translate_m68k_andi_ccr_sr(m68k_options *opts, m68kinst *inst)
2000 {
2001 code_info *code = &opts->gen.code;
2002 cycles(&opts->gen, 20);
2003 //TODO: If ANDI to SR, trap if not in supervisor mode
2004 uint32_t flag_mask = 0;
2005 if (!(inst->src.params.immed & 0x1)) {
2006 flag_mask |= C0;
2007 }
2008 if (!(inst->src.params.immed & 0x2)) {
2009 flag_mask |= V0;
2010 }
2011 if (!(inst->src.params.immed & 0x4)) {
2012 flag_mask |= Z0;
2013 }
2014 if (!(inst->src.params.immed & 0x8)) {
2015 flag_mask |= N0;
2016 }
2017 if (!(inst->src.params.immed & 0x10)) {
2018 flag_mask |= X0;
2019 }
2020 update_flags(opts, flag_mask);
2021 if (inst->op == M68K_ANDI_SR) {
2022 and_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2238 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { 2023 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) {
2239 //leave supervisor mode 2024 //leave supervisor mode
2240 swap_ssp_usp(opts); 2025 swap_ssp_usp(opts);
2241 } 2026 }
2242 code_ptr loop_top = code->cur; 2027 if (inst->src.params.immed & 0x700) {
2243 call(code, opts->do_sync); 2028 call(code, opts->do_sync);
2244 cmp_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D); 2029 }
2245 code_ptr normal_cycle_up = code->cur + 1; 2030 }
2246 jcc(code, CC_A, code->cur + 2); 2031 }
2247 cycles(&opts->gen, BUS); 2032
2248 code_ptr after_cycle_up = code->cur + 1; 2033 void translate_m68k_ori_ccr_sr(m68k_options *opts, m68kinst *inst)
2249 jmp(code, code->cur + 2); 2034 {
2250 *normal_cycle_up = code->cur - (normal_cycle_up + 1); 2035 code_info *code = &opts->gen.code;
2251 mov_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D); 2036 cycles(&opts->gen, 20);
2252 *after_cycle_up = code->cur - (after_cycle_up+1); 2037 //TODO: If ORI to SR, trap if not in supervisor mode
2253 cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D); 2038 uint32_t flag_mask = 0;
2254 jcc(code, CC_C, loop_top); 2039 if (inst->src.params.immed & 0x1) {
2255 break; 2040 flag_mask |= C1;
2256 } 2041 }
2257 //case M68K_TAS: 2042 if (inst->src.params.immed & 0x2) {
2258 case M68K_TRAP: 2043 flag_mask |= V1;
2259 translate_m68k_trap(opts, inst); 2044 }
2260 break; 2045 if (inst->src.params.immed & 0x4) {
2261 //case M68K_TRAPV: 2046 flag_mask |= Z1;
2262 case M68K_TST: 2047 }
2263 case M68K_SWAP: 2048 if (inst->src.params.immed & 0x8) {
2264 translate_m68k_unary(opts, inst, N|Z|V0|C0, &src_op); 2049 flag_mask |= N1;
2265 break; 2050 }
2266 default: 2051 if (inst->src.params.immed & 0x10) {
2267 m68k_disasm(inst, disasm_buf); 2052 flag_mask |= X1;
2268 printf("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op); 2053 }
2269 exit(1); 2054 update_flags(opts, flag_mask);
2270 } 2055 if (inst->op == M68K_ORI_SR) {
2056 or_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2057 if (inst->src.params.immed & 0x700) {
2058 call(code, opts->do_sync);
2059 }
2060 }
2061 }
2062
2063 void translate_m68k_eori_ccr_sr(m68k_options *opts, m68kinst *inst)
2064 {
2065 code_info *code = &opts->gen.code;
2066 cycles(&opts->gen, 20);
2067 //TODO: If ANDI to SR, trap if not in supervisor mode
2068 if (inst->src.params.immed & 0x1) {
2069 xor_flag(opts, 1, FLAG_C);
2070 }
2071 if (inst->src.params.immed & 0x2) {
2072 xor_flag(opts, 1, FLAG_V);
2073 }
2074 if (inst->src.params.immed & 0x4) {
2075 xor_flag(opts, 1, FLAG_Z);
2076 }
2077 if (inst->src.params.immed & 0x8) {
2078 xor_flag(opts, 1, FLAG_N);
2079 }
2080 if (inst->src.params.immed & 0x10) {
2081 xor_flag(opts, 1, FLAG_X);
2082 }
2083 if (inst->op == M68K_ORI_SR) {
2084 xor_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2085 if (inst->src.params.immed & 0x700) {
2086 call(code, opts->do_sync);
2087 }
2088 }
2089 }
2090
2091 void translate_m68k_move_ccr_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
2092 {
2093 code_info *code = &opts->gen.code;
2094 //TODO: Privilege check for MOVE to SR
2095 if (src_op->mode == MODE_IMMED) {
2096 uint32_t flag_mask = src_op->disp & 0x10 ? X1 : X0;
2097 flag_mask |= src_op->disp & 0x8 ? N1 : N0;
2098 flag_mask |= src_op->disp & 0x4 ? Z1 : Z0;
2099 flag_mask |= src_op->disp & 0x2 ? V1 : V0;
2100 flag_mask |= src_op->disp & 0x1 ? C1 : C0;
2101 update_flags(opts, flag_mask);
2102 if (inst->op == M68K_MOVE_SR) {
2103 mov_irdisp(code, (src_op->disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2104 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) {
2105 //leave supervisor mode
2106 mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D);
2107 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_D);
2108 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D);
2109 }
2110 call(code, opts->do_sync);
2111 }
2112 cycles(&opts->gen, 12);
2113 } else {
2114 if (src_op->base != opts->gen.scratch1) {
2115 if (src_op->mode == MODE_REG_DIRECT) {
2116 mov_rr(code, src_op->base, opts->gen.scratch1, SZ_W);
2117 } else {
2118 mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W);
2119 }
2120 }
2121 call(code, inst->op == M68K_MOVE_SR ? opts->set_sr : opts->set_ccr);
2122 cycles(&opts->gen, 12);
2123
2124 }
2125 }
2126
2127 void translate_m68k_stop(m68k_options *opts, m68kinst *inst)
2128 {
2129 //TODO: Trap if not in system mode
2130 //manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction
2131 //possibly even 12 since that's how long MOVE to SR takes
2132 //On further thought prefetch + the fact that this stops the CPU may make
2133 //Motorola's accounting make sense here
2134 code_info *code = &opts->gen.code;
2135 cycles(&opts->gen, BUS*2);
2136 uint32_t flag_mask = inst->src.params.immed & 0x10 ? X1 : X0;
2137 flag_mask |= inst->src.params.immed & 0x8 ? N1 : N0;
2138 flag_mask |= inst->src.params.immed & 0x4 ? Z1 : Z0;
2139 flag_mask |= inst->src.params.immed & 0x2 ? V1 : V0;
2140 flag_mask |= inst->src.params.immed & 0x1 ? C1 : C0;
2141 update_flags(opts, flag_mask);
2142 mov_irdisp(code, (inst->src.params.immed >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2143 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) {
2144 //leave supervisor mode
2145 swap_ssp_usp(opts);
2146 }
2147 code_ptr loop_top = code->cur;
2148 call(code, opts->do_sync);
2149 cmp_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D);
2150 code_ptr normal_cycle_up = code->cur + 1;
2151 jcc(code, CC_A, code->cur + 2);
2152 cycles(&opts->gen, BUS);
2153 code_ptr after_cycle_up = code->cur + 1;
2154 jmp(code, code->cur + 2);
2155 *normal_cycle_up = code->cur - (normal_cycle_up + 1);
2156 mov_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D);
2157 *after_cycle_up = code->cur - (after_cycle_up+1);
2158 cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D);
2159 jcc(code, CC_C, loop_top);
2160 }
2161
2162 void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
2163 {
2164 code_info *code = &opts->gen.code;
2165 //TODO: Trap if not in system mode
2166 call(code, opts->get_sr);
2167 if (dst_op->mode == MODE_REG_DIRECT) {
2168 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_W);
2169 } else {
2170 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_W);
2171 }
2172 m68k_save_result(inst, opts);
2173 }
2174
2175 void translate_m68k_reset(m68k_options *opts, m68kinst *inst)
2176 {
2177 code_info *code = &opts->gen.code;
2178 call(code, opts->gen.save_context);
2179 #ifdef X86_64
2180 mov_rr(code, opts->gen.context_reg, RDI, SZ_PTR);
2181 #else
2182 push_r(code, opts->gen.context_reg);
2183 #endif
2184 call(code, (code_ptr)print_regs_exit);
2185 }
2186
2187 void translate_m68k_rte(m68k_options *opts, m68kinst *inst)
2188 {
2189 code_info *code = &opts->gen.code;
2190 //TODO: Trap if not in system mode
2191 //Read saved SR
2192 areg_to_native(opts, 7, opts->gen.scratch1);
2193 call(code, opts->read_16);
2194 addi_areg(opts, 2, 7);
2195 call(code, opts->set_sr);
2196 //Read saved PC
2197 areg_to_native(opts, 7, opts->gen.scratch1);
2198 call(code, opts->read_32);
2199 addi_areg(opts, 4, 7);
2200 //Check if we've switched to user mode and swap stack pointers if needed
2201 bt_irdisp(code, 5, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2202 code_ptr end_off = code->cur + 1;
2203 jcc(code, CC_C, code->cur + 2);
2204 swap_ssp_usp(opts);
2205 *end_off = code->cur - (end_off+1);
2206 //Get native address, sync components, recalculate integer points and jump to returned address
2207 call(code, opts->native_addr_and_sync);
2208 jmp_r(code, opts->gen.scratch1);
2271 } 2209 }
2272 2210
2273 void translate_out_of_bounds(code_info *code) 2211 void translate_out_of_bounds(code_info *code)
2274 { 2212 {
2275 xor_rr(code, RDI, RDI, SZ_D); 2213 xor_rr(code, RDI, RDI, SZ_D);