Mercurial > repos > blastem
comparison m68k_core_x86.c @ 576:a6f2db4df70d
Small refactor to flag handling in 68K core
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 04 Mar 2014 00:02:20 -0800 |
parents | 1594525e2157 |
children | 0f367276a80c |
comparison
equal
deleted
inserted
replaced
575:f90da1c2ba86 | 576:a6f2db4df70d |
---|---|
113 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B); | 113 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B); |
114 pop_r(code, opts->gen.scratch1); | 114 pop_r(code, opts->gen.scratch1); |
115 } | 115 } |
116 } | 116 } |
117 | 117 |
118 void update_flags(m68k_options *opts, uint32_t update_mask) | |
119 { | |
120 uint8_t native_flags[] = {0, CC_S, CC_Z, CC_O, CC_C}; | |
121 for (int8_t flag = FLAG_C; flag >= FLAG_X; --flag) | |
122 { | |
123 if (update_mask & X0 << (flag*3)) { | |
124 set_flag(opts, 0, flag); | |
125 } else if(update_mask & X1 << (flag*3)) { | |
126 set_flag(opts, 1, flag); | |
127 } else if(update_mask & X << (flag*3)) { | |
128 if (flag == FLAG_X) { | |
129 if (opts->flag_regs[FLAG_C] >= 0 || !(update_mask & (C0|C1|C))) { | |
130 flag_to_flag(opts, FLAG_C, FLAG_X); | |
131 } else if(update_mask & C0) { | |
132 set_flag(opts, 0, flag); | |
133 } else if(update_mask & C1) { | |
134 set_flag(opts, 1, flag); | |
135 } else { | |
136 set_flag_cond(opts, CC_C, flag); | |
137 } | |
138 } else { | |
139 set_flag_cond(opts, native_flags[flag], flag); | |
140 } | |
141 } | |
142 } | |
143 } | |
144 | |
118 void flag_to_carry(m68k_options * opts, uint8_t flag) | 145 void flag_to_carry(m68k_options * opts, uint8_t flag) |
119 { | 146 { |
120 if (opts->flag_regs[flag] >= 0) { | 147 if (opts->flag_regs[flag] >= 0) { |
121 bt_ir(&opts->gen.code, 0, opts->flag_regs[flag], SZ_B); | 148 bt_ir(&opts->gen.code, 0, opts->flag_regs[flag], SZ_B); |
122 } else { | 149 } else { |
510 int32_t offset; | 537 int32_t offset; |
511 int32_t inc_amount, dec_amount; | 538 int32_t inc_amount, dec_amount; |
512 x86_ea src; | 539 x86_ea src; |
513 translate_m68k_op(inst, &src, opts, 0); | 540 translate_m68k_op(inst, &src, opts, 0); |
514 reg = native_reg(&(inst->dst), opts); | 541 reg = native_reg(&(inst->dst), opts); |
515 if (inst->dst.addr_mode != MODE_AREG) { | |
516 //update statically set flags | |
517 set_flag(opts, 0, FLAG_V); | |
518 set_flag(opts, 0, FLAG_C); | |
519 } | |
520 | 542 |
521 if (inst->dst.addr_mode != MODE_AREG) { | 543 if (inst->dst.addr_mode != MODE_AREG) { |
522 if (src.mode == MODE_REG_DIRECT) { | 544 if (src.mode == MODE_REG_DIRECT) { |
523 flags_reg = src.base; | 545 flags_reg = src.base; |
524 } else { | 546 } else { |
552 } else if(src.mode == MODE_REG_DIRECT) { | 574 } else if(src.mode == MODE_REG_DIRECT) { |
553 mov_rrdisp(code, src.base, opts->gen.context_reg, reg_offset(&(inst->dst)), size); | 575 mov_rrdisp(code, src.base, opts->gen.context_reg, reg_offset(&(inst->dst)), size); |
554 } else { | 576 } else { |
555 mov_irdisp(code, src.disp, opts->gen.context_reg, reg_offset(&(inst->dst)), size); | 577 mov_irdisp(code, src.disp, opts->gen.context_reg, reg_offset(&(inst->dst)), size); |
556 } | 578 } |
557 if (inst->dst.addr_mode != MODE_AREG) { | |
558 cmp_ir(code, 0, flags_reg, size); | |
559 set_flag_cond(opts, CC_Z, FLAG_Z); | |
560 set_flag_cond(opts, CC_S, FLAG_N); | |
561 } | |
562 break; | 579 break; |
563 case MODE_AREG_PREDEC: | 580 case MODE_AREG_PREDEC: |
564 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); | 581 dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); |
565 subi_areg(opts, dec_amount, inst->dst.params.regs.pri); | 582 subi_areg(opts, dec_amount, inst->dst.params.regs.pri); |
566 case MODE_AREG_INDIRECT: | 583 case MODE_AREG_INDIRECT: |
573 } else if (src.mode == MODE_REG_DISPLACE8) { | 590 } else if (src.mode == MODE_REG_DISPLACE8) { |
574 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); | 591 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); |
575 } else { | 592 } else { |
576 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); | 593 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); |
577 } | 594 } |
578 if (inst->dst.addr_mode != MODE_AREG) { | |
579 cmp_ir(code, 0, flags_reg, inst->extra.size); | |
580 set_flag_cond(opts, CC_Z, FLAG_Z); | |
581 set_flag_cond(opts, CC_S, FLAG_N); | |
582 } | |
583 m68k_write_size(opts, inst->extra.size); | |
584 | |
585 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { | |
586 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); | |
587 addi_areg(opts, inc_amount, inst->dst.params.regs.pri); | |
588 } | |
589 break; | 595 break; |
590 case MODE_AREG_DISPLACE: | 596 case MODE_AREG_DISPLACE: |
591 cycles(&opts->gen, BUS); | 597 cycles(&opts->gen, BUS); |
592 calc_areg_displace(opts, &inst->dst, opts->gen.scratch2); | 598 calc_areg_displace(opts, &inst->dst, opts->gen.scratch2); |
593 if (src.mode == MODE_REG_DIRECT) { | 599 if (src.mode == MODE_REG_DIRECT) { |
597 } else if (src.mode == MODE_REG_DISPLACE8) { | 603 } else if (src.mode == MODE_REG_DISPLACE8) { |
598 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); | 604 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); |
599 } else { | 605 } else { |
600 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); | 606 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); |
601 } | 607 } |
602 if (inst->dst.addr_mode != MODE_AREG) { | |
603 cmp_ir(code, 0, flags_reg, inst->extra.size); | |
604 set_flag_cond(opts, CC_Z, FLAG_Z); | |
605 set_flag_cond(opts, CC_S, FLAG_N); | |
606 } | |
607 m68k_write_size(opts, inst->extra.size); | |
608 break; | 608 break; |
609 case MODE_AREG_INDEX_DISP8: | 609 case MODE_AREG_INDEX_DISP8: |
610 cycles(&opts->gen, 6);//TODO: Check to make sure this is correct | 610 cycles(&opts->gen, 6);//TODO: Check to make sure this is correct |
611 //calc_areg_index_disp8 will clober scratch1 when a 16-bit index is used | 611 //calc_areg_index_disp8 will clober scratch1 when a 16-bit index is used |
612 if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) { | 612 if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) { |
623 } else if (src.mode == MODE_REG_DISPLACE8) { | 623 } else if (src.mode == MODE_REG_DISPLACE8) { |
624 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); | 624 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); |
625 } else { | 625 } else { |
626 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); | 626 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); |
627 } | 627 } |
628 if (inst->dst.addr_mode != MODE_AREG) { | |
629 cmp_ir(code, 0, flags_reg, inst->extra.size); | |
630 set_flag_cond(opts, CC_Z, FLAG_Z); | |
631 set_flag_cond(opts, CC_S, FLAG_N); | |
632 } | |
633 m68k_write_size(opts, inst->extra.size); | |
634 break; | 628 break; |
635 case MODE_PC_DISPLACE: | 629 case MODE_PC_DISPLACE: |
636 cycles(&opts->gen, BUS); | 630 cycles(&opts->gen, BUS); |
637 mov_ir(code, inst->dst.params.regs.displacement + inst->address+2, opts->gen.scratch2, SZ_D); | 631 mov_ir(code, inst->dst.params.regs.displacement + inst->address+2, opts->gen.scratch2, SZ_D); |
638 if (src.mode == MODE_REG_DIRECT) { | 632 if (src.mode == MODE_REG_DIRECT) { |
642 } else if (src.mode == MODE_REG_DISPLACE8) { | 636 } else if (src.mode == MODE_REG_DISPLACE8) { |
643 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); | 637 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); |
644 } else { | 638 } else { |
645 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); | 639 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); |
646 } | 640 } |
647 if (inst->dst.addr_mode != MODE_AREG) { | |
648 cmp_ir(code, 0, flags_reg, inst->extra.size); | |
649 set_flag_cond(opts, CC_Z, FLAG_Z); | |
650 set_flag_cond(opts, CC_S, FLAG_N); | |
651 } | |
652 m68k_write_size(opts, inst->extra.size); | |
653 break; | 641 break; |
654 case MODE_PC_INDEX_DISP8: | 642 case MODE_PC_INDEX_DISP8: |
655 cycles(&opts->gen, 6);//TODO: Check to make sure this is correct | 643 cycles(&opts->gen, 6);//TODO: Check to make sure this is correct |
656 mov_ir(code, inst->address, opts->gen.scratch2, SZ_D); | 644 mov_ir(code, inst->address, opts->gen.scratch2, SZ_D); |
657 if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) { | 645 if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) { |
668 } else if (src.mode == MODE_REG_DISPLACE8) { | 656 } else if (src.mode == MODE_REG_DISPLACE8) { |
669 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); | 657 mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size); |
670 } else { | 658 } else { |
671 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); | 659 mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size); |
672 } | 660 } |
673 if (inst->dst.addr_mode != MODE_AREG) { | |
674 cmp_ir(code, 0, flags_reg, inst->extra.size); | |
675 set_flag_cond(opts, CC_Z, FLAG_Z); | |
676 set_flag_cond(opts, CC_S, FLAG_N); | |
677 } | |
678 m68k_write_size(opts, inst->extra.size); | |
679 break; | 661 break; |
680 case MODE_ABSOLUTE: | 662 case MODE_ABSOLUTE: |
681 case MODE_ABSOLUTE_SHORT: | 663 case MODE_ABSOLUTE_SHORT: |
682 if (src.mode == MODE_REG_DIRECT) { | 664 if (src.mode == MODE_REG_DIRECT) { |
683 if (src.base != opts->gen.scratch1) { | 665 if (src.base != opts->gen.scratch1) { |
692 cycles(&opts->gen, BUS*2); | 674 cycles(&opts->gen, BUS*2); |
693 } else { | 675 } else { |
694 cycles(&opts->gen, BUS); | 676 cycles(&opts->gen, BUS); |
695 } | 677 } |
696 mov_ir(code, inst->dst.params.immed, opts->gen.scratch2, SZ_D); | 678 mov_ir(code, inst->dst.params.immed, opts->gen.scratch2, SZ_D); |
697 if (inst->dst.addr_mode != MODE_AREG) { | |
698 cmp_ir(code, 0, flags_reg, inst->extra.size); | |
699 set_flag_cond(opts, CC_Z, FLAG_Z); | |
700 set_flag_cond(opts, CC_S, FLAG_N); | |
701 } | |
702 m68k_write_size(opts, inst->extra.size); | |
703 break; | 679 break; |
704 default: | 680 default: |
705 m68k_disasm(inst, disasm_buf); | 681 m68k_disasm(inst, disasm_buf); |
706 printf("%X: %s\naddress mode %d not implemented (move dst)\n", inst->address, disasm_buf, inst->dst.addr_mode); | 682 printf("%X: %s\naddress mode %d not implemented (move dst)\n", inst->address, disasm_buf, inst->dst.addr_mode); |
707 exit(1); | 683 exit(1); |
684 } | |
685 | |
686 if (inst->dst.addr_mode != MODE_AREG) { | |
687 cmp_ir(code, 0, flags_reg, inst->extra.size); | |
688 update_flags(opts, N|Z|V0|C0); | |
689 } | |
690 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG) { | |
691 m68k_write_size(opts, inst->extra.size); | |
692 if (inst->dst.addr_mode == MODE_AREG_POSTINC) { | |
693 inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1)); | |
694 addi_areg(opts, inc_amount, inst->dst.params.regs.pri); | |
695 } | |
708 } | 696 } |
709 | 697 |
710 //add cycles for prefetch | 698 //add cycles for prefetch |
711 cycles(&opts->gen, BUS); | 699 cycles(&opts->gen, BUS); |
712 } | 700 } |
854 } | 842 } |
855 | 843 |
856 void translate_m68k_clr(m68k_options * opts, m68kinst * inst) | 844 void translate_m68k_clr(m68k_options * opts, m68kinst * inst) |
857 { | 845 { |
858 code_info *code = &opts->gen.code; | 846 code_info *code = &opts->gen.code; |
859 set_flag(opts, 0, FLAG_N); | 847 update_flags(opts, N0|V0|C0|Z1); |
860 set_flag(opts, 0, FLAG_V); | |
861 set_flag(opts, 0, FLAG_C); | |
862 set_flag(opts, 1, FLAG_Z); | |
863 int8_t reg = native_reg(&(inst->dst), opts); | 848 int8_t reg = native_reg(&(inst->dst), opts); |
864 if (reg >= 0) { | 849 if (reg >= 0) { |
865 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 6 : 4)); | 850 cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 6 : 4)); |
866 xor_rr(code, reg, reg, inst->extra.size); | 851 xor_rr(code, reg, reg, inst->extra.size); |
867 return; | 852 return; |
868 } | 853 } |
869 x86_ea dst_op; | 854 x86_ea dst_op; |
855 //TODO: fix timing | |
870 translate_m68k_op(inst, &dst_op, opts, 1); | 856 translate_m68k_op(inst, &dst_op, opts, 1); |
871 if (dst_op.mode == MODE_REG_DIRECT) { | 857 if (dst_op.mode == MODE_REG_DIRECT) { |
872 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); |
873 } else { | 859 } else { |
874 mov_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size); | 860 mov_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size); |
890 movsx_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, inst->extra.size, dst_size); | 876 movsx_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, inst->extra.size, dst_size); |
891 cmp_ir(code, 0, opts->gen.scratch1, dst_size); | 877 cmp_ir(code, 0, opts->gen.scratch1, dst_size); |
892 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, dst_size); | 878 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, dst_size); |
893 } | 879 } |
894 inst->extra.size = dst_size; | 880 inst->extra.size = dst_size; |
895 set_flag(opts, 0, FLAG_V); | 881 update_flags(opts, N|V0|C0|Z); |
896 set_flag(opts, 0, FLAG_C); | |
897 set_flag_cond(opts, CC_Z, FLAG_Z); | |
898 set_flag_cond(opts, CC_S, FLAG_N); | |
899 //M68K EXT only operates on registers so no need for a call to save result here | 882 //M68K EXT only operates on registers so no need for a call to save result here |
900 } | 883 } |
901 | 884 |
902 uint8_t m68k_eval_cond(m68k_options * opts, uint8_t cc) | 885 uint8_t m68k_eval_cond(m68k_options * opts, uint8_t cc) |
903 { | 886 { |
1170 cmp_ir(code, src_op.disp, dst_op.base, size); | 1153 cmp_ir(code, src_op.disp, dst_op.base, size); |
1171 } else { | 1154 } else { |
1172 cmp_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, size); | 1155 cmp_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, size); |
1173 } | 1156 } |
1174 } | 1157 } |
1175 set_flag_cond(opts, CC_C, FLAG_C); | 1158 update_flags(opts, N|Z|V|C); |
1176 set_flag_cond(opts, CC_Z, FLAG_Z); | |
1177 set_flag_cond(opts, CC_S, FLAG_N); | |
1178 set_flag_cond(opts, CC_O, FLAG_V); | |
1179 } | 1159 } |
1180 | 1160 |
1181 typedef void (*shift_ir_t)(code_info *code, uint8_t val, uint8_t dst, uint8_t size); | 1161 typedef void (*shift_ir_t)(code_info *code, uint8_t val, uint8_t dst, uint8_t size); |
1182 typedef void (*shift_irdisp_t)(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size); | 1162 typedef void (*shift_irdisp_t)(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size); |
1183 typedef void (*shift_clr_t)(code_info *code, uint8_t dst, uint8_t size); | 1163 typedef void (*shift_clr_t)(code_info *code, uint8_t dst, uint8_t size); |
1458 } else { | 1438 } else { |
1459 add_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, size); | 1439 add_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, size); |
1460 } | 1440 } |
1461 } | 1441 } |
1462 if (inst->dst.addr_mode != MODE_AREG) { | 1442 if (inst->dst.addr_mode != MODE_AREG) { |
1463 set_flag_cond(opts, CC_C, FLAG_C); | 1443 update_flags(opts, X|N|Z|V|C); |
1464 set_flag_cond(opts, CC_Z, FLAG_Z); | |
1465 set_flag_cond(opts, CC_S, FLAG_N); | |
1466 set_flag_cond(opts, CC_O, FLAG_V); | |
1467 if (opts->flag_regs[FLAG_C] >= 0) { | |
1468 flag_to_flag(opts, FLAG_C, FLAG_X); | |
1469 } else { | |
1470 set_flag_cond(opts, CC_C, FLAG_X); | |
1471 } | |
1472 } | 1444 } |
1473 m68k_save_result(inst, opts); | 1445 m68k_save_result(inst, opts); |
1474 break; | 1446 break; |
1475 case M68K_ADDX: { | 1447 case M68K_ADDX: { |
1476 cycles(&opts->gen, BUS); | 1448 cycles(&opts->gen, BUS); |
1522 and_ir(code, src_op.disp, dst_op.base, inst->extra.size); | 1494 and_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
1523 } else { | 1495 } else { |
1524 and_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 1496 and_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
1525 } | 1497 } |
1526 } | 1498 } |
1527 set_flag(opts, 0, FLAG_C); | 1499 update_flags(opts, N|Z|V0|C0); |
1528 set_flag_cond(opts, CC_Z, FLAG_Z); | |
1529 set_flag_cond(opts, CC_S, FLAG_N); | |
1530 set_flag(opts, 0, FLAG_V); | |
1531 m68k_save_result(inst, opts); | 1500 m68k_save_result(inst, opts); |
1532 break; | 1501 break; |
1533 case M68K_ANDI_CCR: | 1502 case M68K_ANDI_CCR: |
1534 case M68K_ANDI_SR: | 1503 case M68K_ANDI_SR: { |
1535 cycles(&opts->gen, 20); | 1504 cycles(&opts->gen, 20); |
1536 //TODO: If ANDI to SR, trap if not in supervisor mode | 1505 //TODO: If ANDI to SR, trap if not in supervisor mode |
1506 uint32_t flag_mask = 0; | |
1537 if (!(inst->src.params.immed & 0x1)) { | 1507 if (!(inst->src.params.immed & 0x1)) { |
1538 set_flag(opts, 0, FLAG_C); | 1508 flag_mask |= C0; |
1539 } | 1509 } |
1540 if (!(inst->src.params.immed & 0x2)) { | 1510 if (!(inst->src.params.immed & 0x2)) { |
1541 set_flag(opts, 0, FLAG_V); | 1511 flag_mask |= V0; |
1542 } | 1512 } |
1543 if (!(inst->src.params.immed & 0x4)) { | 1513 if (!(inst->src.params.immed & 0x4)) { |
1544 set_flag(opts, 0, FLAG_Z); | 1514 flag_mask |= Z0; |
1545 } | 1515 } |
1546 if (!(inst->src.params.immed & 0x8)) { | 1516 if (!(inst->src.params.immed & 0x8)) { |
1547 set_flag(opts, 0, FLAG_N); | 1517 flag_mask |= N0; |
1548 } | 1518 } |
1549 if (!(inst->src.params.immed & 0x10)) { | 1519 if (!(inst->src.params.immed & 0x10)) { |
1550 set_flag(opts, 0, FLAG_X); | 1520 flag_mask |= X0; |
1551 } | 1521 } |
1522 update_flags(opts, flag_mask); | |
1552 if (inst->op == M68K_ANDI_SR) { | 1523 if (inst->op == M68K_ANDI_SR) { |
1553 and_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); | 1524 and_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
1554 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { | 1525 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { |
1555 //leave supervisor mode | 1526 //leave supervisor mode |
1556 mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_B); | 1527 swap_ssp_usp(opts); |
1557 mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, opts->aregs[7], SZ_B); | |
1558 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_B); | |
1559 } | 1528 } |
1560 if (inst->src.params.immed & 0x700) { | 1529 if (inst->src.params.immed & 0x700) { |
1561 call(code, opts->do_sync); | 1530 call(code, opts->do_sync); |
1562 } | 1531 } |
1563 } | 1532 } |
1564 break; | 1533 break; |
1534 } | |
1565 case M68K_ASL: | 1535 case M68K_ASL: |
1566 case M68K_LSL: | 1536 case M68K_LSL: |
1567 translate_shift(opts, inst, &src_op, &dst_op, shl_ir, shl_irdisp, shl_clr, shl_clrdisp, shr_ir, shr_irdisp); | 1537 translate_shift(opts, inst, &src_op, &dst_op, shl_ir, shl_irdisp, shl_clr, shl_clrdisp, shr_ir, shr_irdisp); |
1568 break; | 1538 break; |
1569 case M68K_ASR: | 1539 case M68K_ASR: |
1848 xor_ir(code, src_op.disp, dst_op.base, inst->extra.size); | 1818 xor_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
1849 } else { | 1819 } else { |
1850 xor_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 1820 xor_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
1851 } | 1821 } |
1852 } | 1822 } |
1853 set_flag(opts, 0, FLAG_C); | 1823 update_flags(opts, N|Z|V0|C0); |
1854 set_flag_cond(opts, CC_Z, FLAG_Z); | |
1855 set_flag_cond(opts, CC_S, FLAG_N); | |
1856 set_flag(opts, 0, FLAG_V); | |
1857 m68k_save_result(inst, opts); | 1824 m68k_save_result(inst, opts); |
1858 break; | 1825 break; |
1859 case M68K_EORI_CCR: | 1826 case M68K_EORI_CCR: |
1860 case M68K_EORI_SR: | 1827 case M68K_EORI_SR: |
1861 cycles(&opts->gen, 20); | 1828 cycles(&opts->gen, 20); |
1926 break; | 1893 break; |
1927 case M68K_MOVE_CCR: | 1894 case M68K_MOVE_CCR: |
1928 case M68K_MOVE_SR: | 1895 case M68K_MOVE_SR: |
1929 //TODO: Privilege check for MOVE to SR | 1896 //TODO: Privilege check for MOVE to SR |
1930 if (src_op.mode == MODE_IMMED) { | 1897 if (src_op.mode == MODE_IMMED) { |
1931 set_flag(opts, src_op.disp & 0x1, FLAG_C); | 1898 uint32_t flag_mask = src_op.disp & 0x10 ? X1 : X0; |
1932 set_flag(opts, (src_op.disp >> 1) & 0x1, FLAG_V); | 1899 flag_mask |= src_op.disp & 0x8 ? N1 : N0; |
1933 set_flag(opts, (src_op.disp >> 2) & 0x1, FLAG_Z); | 1900 flag_mask |= src_op.disp & 0x4 ? Z1 : Z0; |
1934 set_flag(opts, (src_op.disp >> 3) & 0x1, FLAG_N); | 1901 flag_mask |= src_op.disp & 0x2 ? V1 : V0; |
1935 set_flag(opts, (src_op.disp >> 4) & 0x1, FLAG_X); | 1902 flag_mask |= src_op.disp & 0x1 ? C1 : C0; |
1903 update_flags(opts, flag_mask); | |
1936 if (inst->op == M68K_MOVE_SR) { | 1904 if (inst->op == M68K_MOVE_SR) { |
1937 mov_irdisp(code, (src_op.disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); | 1905 mov_irdisp(code, (src_op.disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
1938 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { | 1906 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { |
1939 //leave supervisor mode | 1907 //leave supervisor mode |
1940 mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); | 1908 mov_rr(code, opts->aregs[7], opts->gen.scratch1, SZ_D); |
2010 } | 1978 } |
2011 imul_rr(code, opts->gen.scratch1, dst_reg, SZ_D); | 1979 imul_rr(code, opts->gen.scratch1, dst_reg, SZ_D); |
2012 if (dst_op.mode == MODE_REG_DISPLACE8) { | 1980 if (dst_op.mode == MODE_REG_DISPLACE8) { |
2013 mov_rrdisp(code, dst_reg, dst_op.base, dst_op.disp, SZ_D); | 1981 mov_rrdisp(code, dst_reg, dst_op.base, dst_op.disp, SZ_D); |
2014 } | 1982 } |
2015 set_flag(opts, 0, FLAG_V); | |
2016 set_flag(opts, 0, FLAG_C); | |
2017 cmp_ir(code, 0, dst_reg, SZ_D); | 1983 cmp_ir(code, 0, dst_reg, SZ_D); |
2018 set_flag_cond(opts, CC_Z, FLAG_Z); | 1984 update_flags(opts, N|Z|V0|C0); |
2019 set_flag_cond(opts, CC_S, FLAG_N); | |
2020 break; | 1985 break; |
2021 //case M68K_NBCD: | 1986 //case M68K_NBCD: |
2022 case M68K_NEG: | 1987 case M68K_NEG: |
2023 cycles(&opts->gen, BUS); | 1988 cycles(&opts->gen, BUS); |
2024 if (dst_op.mode == MODE_REG_DIRECT) { | 1989 if (dst_op.mode == MODE_REG_DIRECT) { |
2025 neg_r(code, dst_op.base, inst->extra.size); | 1990 neg_r(code, dst_op.base, inst->extra.size); |
2026 } else { | 1991 } else { |
2027 neg_rdisp(code, dst_op.base, dst_op.disp, inst->extra.size); | 1992 neg_rdisp(code, dst_op.base, dst_op.disp, inst->extra.size); |
2028 } | 1993 } |
2029 set_flag_cond(opts, CC_C, FLAG_C); | 1994 update_flags(opts, X|N|Z|V|C); |
2030 set_flag_cond(opts, CC_Z, FLAG_Z); | |
2031 set_flag_cond(opts, CC_S, FLAG_N); | |
2032 set_flag_cond(opts, CC_O, FLAG_V); | |
2033 if (opts->flag_regs[FLAG_C] >= 0) { | |
2034 flag_to_flag(opts, FLAG_C, FLAG_X); | |
2035 } else { | |
2036 set_flag_cond(opts, CC_C, FLAG_X); | |
2037 } | |
2038 m68k_save_result(inst, opts); | 1995 m68k_save_result(inst, opts); |
2039 break; | 1996 break; |
2040 case M68K_NEGX: { | 1997 case M68K_NEGX: { |
2041 cycles(&opts->gen, BUS); | 1998 cycles(&opts->gen, BUS); |
2042 if (dst_op.mode == MODE_REG_DIRECT) { | 1999 if (dst_op.mode == MODE_REG_DIRECT) { |
2084 } else { | 2041 } else { |
2085 not_rdisp(code, dst_op.base, dst_op.disp, inst->extra.size); | 2042 not_rdisp(code, dst_op.base, dst_op.disp, inst->extra.size); |
2086 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size); | 2043 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, inst->extra.size); |
2087 } | 2044 } |
2088 | 2045 |
2089 set_flag(opts, 0, FLAG_C); | 2046 update_flags(opts, N|Z|V0|C0); |
2090 set_flag_cond(opts, CC_Z, FLAG_Z); | |
2091 set_flag_cond(opts, CC_S, FLAG_N); | |
2092 set_flag(opts, 0, FLAG_V); | |
2093 m68k_save_result(inst, opts); | 2047 m68k_save_result(inst, opts); |
2094 break; | 2048 break; |
2095 case M68K_OR: | 2049 case M68K_OR: |
2096 cycles(&opts->gen, BUS); | 2050 cycles(&opts->gen, BUS); |
2097 if (src_op.mode == MODE_REG_DIRECT) { | 2051 if (src_op.mode == MODE_REG_DIRECT) { |
2107 or_ir(code, src_op.disp, dst_op.base, inst->extra.size); | 2061 or_ir(code, src_op.disp, dst_op.base, inst->extra.size); |
2108 } else { | 2062 } else { |
2109 or_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); | 2063 or_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); |
2110 } | 2064 } |
2111 } | 2065 } |
2112 set_flag(opts, 0, FLAG_C); | 2066 update_flags(opts, N|Z|V0|C0); |
2113 set_flag_cond(opts, CC_Z, FLAG_Z); | |
2114 set_flag_cond(opts, CC_S, FLAG_N); | |
2115 set_flag(opts, 0, FLAG_V); | |
2116 m68k_save_result(inst, opts); | 2067 m68k_save_result(inst, opts); |
2117 break; | 2068 break; |
2118 case M68K_ORI_CCR: | 2069 case M68K_ORI_CCR: |
2119 case M68K_ORI_SR: | 2070 case M68K_ORI_SR: |
2120 cycles(&opts->gen, 20); | 2071 cycles(&opts->gen, 20); |
2121 //TODO: If ANDI to SR, trap if not in supervisor mode | 2072 //TODO: If ORI to SR, trap if not in supervisor mode |
2073 uint32_t flag_mask = 0; | |
2122 if (inst->src.params.immed & 0x1) { | 2074 if (inst->src.params.immed & 0x1) { |
2123 set_flag(opts, 1, FLAG_C); | 2075 flag_mask |= C1; |
2124 } | 2076 } |
2125 if (inst->src.params.immed & 0x2) { | 2077 if (inst->src.params.immed & 0x2) { |
2126 set_flag(opts, 1, FLAG_V); | 2078 flag_mask |= V1; |
2127 } | 2079 } |
2128 if (inst->src.params.immed & 0x4) { | 2080 if (inst->src.params.immed & 0x4) { |
2129 set_flag(opts, 1, FLAG_Z); | 2081 flag_mask |= Z1; |
2130 } | 2082 } |
2131 if (inst->src.params.immed & 0x8) { | 2083 if (inst->src.params.immed & 0x8) { |
2132 set_flag(opts, 1, FLAG_N); | 2084 flag_mask |= N1; |
2133 } | 2085 } |
2134 if (inst->src.params.immed & 0x10) { | 2086 if (inst->src.params.immed & 0x10) { |
2135 set_flag(opts, 1, FLAG_X); | 2087 flag_mask |= X1; |
2136 } | 2088 } |
2089 update_flags(opts, flag_mask); | |
2137 if (inst->op == M68K_ORI_SR) { | 2090 if (inst->op == M68K_ORI_SR) { |
2138 or_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); | 2091 or_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
2139 if (inst->src.params.immed & 0x700) { | 2092 if (inst->src.params.immed & 0x700) { |
2140 call(code, opts->do_sync); | 2093 call(code, opts->do_sync); |
2141 } | 2094 } |
2429 case M68K_STOP: { | 2382 case M68K_STOP: { |
2430 //TODO: Trap if not in system mode | 2383 //TODO: Trap if not in system mode |
2431 //manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction | 2384 //manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction |
2432 //possibly even 12 since that's how long MOVE to SR takes | 2385 //possibly even 12 since that's how long MOVE to SR takes |
2433 cycles(&opts->gen, BUS*2); | 2386 cycles(&opts->gen, BUS*2); |
2434 set_flag(opts, src_op.disp & 0x1, FLAG_C); | 2387 uint32_t flag_mask = src_op.disp & 0x10 ? X1 : X0; |
2435 set_flag(opts, (src_op.disp >> 1) & 0x1, FLAG_V); | 2388 flag_mask |= src_op.disp & 0x8 ? N1 : N0; |
2436 set_flag(opts, (src_op.disp >> 2) & 0x1, FLAG_Z); | 2389 flag_mask |= src_op.disp & 0x4 ? Z1 : Z0; |
2437 set_flag(opts, (src_op.disp >> 3) & 0x1, FLAG_N); | 2390 flag_mask |= src_op.disp & 0x2 ? V1 : V0; |
2438 set_flag(opts, (src_op.disp >> 4) & 0x1, FLAG_X); | 2391 flag_mask |= src_op.disp & 0x1 ? C1 : C0; |
2392 update_flags(opts, flag_mask); | |
2439 mov_irdisp(code, (src_op.disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); | 2393 mov_irdisp(code, (src_op.disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
2440 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { | 2394 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { |
2441 //leave supervisor mode | 2395 //leave supervisor mode |
2442 swap_ssp_usp(opts); | 2396 swap_ssp_usp(opts); |
2443 } | 2397 } |
2473 } else { | 2427 } else { |
2474 sub_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, size); | 2428 sub_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, size); |
2475 } | 2429 } |
2476 } | 2430 } |
2477 if (inst->dst.addr_mode != MODE_AREG) { | 2431 if (inst->dst.addr_mode != MODE_AREG) { |
2478 set_flag_cond(opts, CC_C, FLAG_C); | 2432 update_flags(opts, X|N|Z|V|C); |
2479 set_flag_cond(opts, CC_Z, FLAG_Z); | |
2480 set_flag_cond(opts, CC_S, FLAG_N); | |
2481 set_flag_cond(opts, CC_O, FLAG_V); | |
2482 if (opts->flag_regs[FLAG_C] >= 0) { | |
2483 flag_to_flag(opts, FLAG_C, FLAG_X); | |
2484 } else { | |
2485 set_flag_cond(opts, CC_C, FLAG_X); | |
2486 } | |
2487 } | 2433 } |
2488 m68k_save_result(inst, opts); | 2434 m68k_save_result(inst, opts); |
2489 break; | 2435 break; |
2490 case M68K_SUBX: { | 2436 case M68K_SUBX: { |
2491 cycles(&opts->gen, BUS); | 2437 cycles(&opts->gen, BUS); |
2529 } else{ | 2475 } else{ |
2530 rol_irdisp(code, 16, src_op.base, src_op.disp, SZ_D); | 2476 rol_irdisp(code, 16, src_op.base, src_op.disp, SZ_D); |
2531 cmp_irdisp(code, 0, src_op.base, src_op.disp, SZ_D); | 2477 cmp_irdisp(code, 0, src_op.base, src_op.disp, SZ_D); |
2532 } | 2478 } |
2533 | 2479 |
2534 set_flag(opts, 0, FLAG_C); | 2480 update_flags(opts, N|Z|V0|C0); |
2535 set_flag_cond(opts, CC_Z, FLAG_Z); | |
2536 set_flag_cond(opts, CC_S, FLAG_N); | |
2537 set_flag(opts, 0, FLAG_V); | |
2538 break; | 2481 break; |
2539 //case M68K_TAS: | 2482 //case M68K_TAS: |
2540 case M68K_TRAP: | 2483 case M68K_TRAP: |
2541 translate_m68k_trap(opts, inst); | 2484 translate_m68k_trap(opts, inst); |
2542 break; | 2485 break; |
2546 if (src_op.mode == MODE_REG_DIRECT) { | 2489 if (src_op.mode == MODE_REG_DIRECT) { |
2547 cmp_ir(code, 0, src_op.base, inst->extra.size); | 2490 cmp_ir(code, 0, src_op.base, inst->extra.size); |
2548 } else { //M68000 doesn't support immedate operand for tst, so this must be MODE_REG_DISPLACE8 | 2491 } else { //M68000 doesn't support immedate operand for tst, so this must be MODE_REG_DISPLACE8 |
2549 cmp_irdisp(code, 0, src_op.base, src_op.disp, inst->extra.size); | 2492 cmp_irdisp(code, 0, src_op.base, src_op.disp, inst->extra.size); |
2550 } | 2493 } |
2551 set_flag(opts, 0, FLAG_C); | 2494 update_flags(opts, N|Z|V0|C0); |
2552 set_flag_cond(opts, CC_Z, FLAG_Z); | |
2553 set_flag_cond(opts, CC_S, FLAG_N); | |
2554 set_flag(opts, 0, FLAG_V); | |
2555 break; | 2495 break; |
2556 default: | 2496 default: |
2557 m68k_disasm(inst, disasm_buf); | 2497 m68k_disasm(inst, disasm_buf); |
2558 printf("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op); | 2498 printf("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op); |
2559 exit(1); | 2499 exit(1); |