--- tme/ic/m68k/m68k-insns-auto.sh 2018/04/24 16:39:03 1.1.1.2 +++ tme/ic/m68k/m68k-insns-auto.sh 2018/04/24 16:40:24 1.1.1.3 @@ -1,6 +1,6 @@ #! /bin/sh -# $Id: m68k-insns-auto.sh,v 1.1.1.2 2018/04/24 16:39:03 root Exp $ +# $Id: m68k-insns-auto.sh,v 1.1.1.3 2018/04/24 16:40:24 root Exp $ # ic/m68k/m68k-insns-auto.sh - automatically generates C code # for many m68k emulation instructions: @@ -48,7 +48,7 @@ done PROG=`basename $0` cat < 0) {" case "${name}" in - [al]sr) + lsr) echo " if (63 > SHIFTMAX_INT${size}_T" echo " && count > ${size}) {" echo " res = 0;" @@ -458,6 +458,27 @@ for size in 8 16 32; do echo " flags |= (flags * TME_M68K_FLAG_X);" echo " res >>= 1;" ;; + asr) + echo " if (63 > SHIFTMAX_INT${size}_T" + echo " && count > ${size}) {" + echo " res = 0 - (res < 0);" + echo " }" + echo "#ifdef SHIFTSIGNED_INT${size}_T" + echo " res >>= (count - 1);" + echo "#else /* !SHIFTSIGNED_INT${size}_T */" + echo " for (; --count > 0; ) {" + echo " res = (res & ~((tme_${sign}int${size}_t) 1)) / 2;" + echo " }" + echo "#endif /* !SHIFTSIGNED_INT${size}_T */" + echo " flags = (res & 1);" + echo " flags *= TME_M68K_FLAG_C;" + echo " flags |= (flags * TME_M68K_FLAG_X);" + echo "#ifdef SHIFTSIGNED_INT${size}_T" + echo " res >>= 1;" + echo "#else /* !SHIFTSIGNED_INT${size}_T */" + echo " res = (res & ~((tme_${sign}int${size}_t) 1)) / 2;" + echo "#endif /* !SHIFTSIGNED_INT${size}_T */" + ;; [al]sl) if test ${name} = asl; then echo "" @@ -740,13 +761,15 @@ for size in 8 16 32; do echo "{" echo " if (*((tme_int${size}_t *) _op0) < 0) {" echo " ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_N;" + echo " ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;" echo " ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;" - echo " TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_GROUP2(6));" + echo " TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK));" echo " }" echo " if (*((tme_int${size}_t *) _op0) > *((tme_int${size}_t *) _op1)) {" echo " ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_N;" + echo " ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;" echo " ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;" - echo " TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_GROUP2(6));" + echo " TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK));" echo " }" echo " TME_M68K_INSN_OK;" echo "}" @@ -775,7 +798,7 @@ for size in 8 16 32; do echo " int do_write;" echo " tme_uint16_t specopx = ic->_tme_m68k_insn_specop;" if test $name = cas2_; then - echo " tme_uint16_t specopy = ic->_tme_m68k_insn_specop2;" + echo " tme_uint16_t specopy = TME_M68K_INSN_OP0(tme_uint16_t);" echo " tme_uint32_t addrx;" echo " tme_uint32_t addry;" echo "" @@ -877,11 +900,38 @@ for size in 8 16 32; do echo "TME_M68K_INSN(tme_m68k_moves${size})" echo "{" echo " int ireg;" + echo " unsigned int ea_reg;" + echo " unsigned int increment;" + echo " TME_M68K_INSN_PRIV;" + echo " TME_M68K_INSN_CANFAULT;" echo " ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4);" + echo "" + echo " /* we have to handle postincrement and predecrement ourselves: */" + echo " if (!TME_M68K_SEQUENCE_RESTARTING) {" + echo " ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);" + echo " increment = TME_M68K_SIZE_${size};" + echo " if (increment == TME_M68K_SIZE_8 && ea_reg == TME_M68K_IREG_A7) {" + echo " increment = TME_M68K_SIZE_16;" + echo " }" + echo " switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3)) {" + echo " case 3: ic->tme_m68k_ireg_uint32(ea_reg) += increment; break;" + echo " case 4: ic->_tme_m68k_ea_address = (ic->tme_m68k_ireg_uint32(ea_reg) -= increment); break;" + echo " default: break;" + echo " }" + echo " }" + echo "" echo " if (TME_M68K_INSN_SPECOP & TME_BIT(11)) {" - echo " ic->tme_m68k_ireg_memx${size} = ic->tme_m68k_ireg_uint${size}(ireg${reg_size_shift});" + echo " if (!TME_M68K_SEQUENCE_RESTARTING) {" + echo " ic->tme_m68k_ireg_memx${size} = ic->tme_m68k_ireg_uint${size}(ireg${reg_size_shift});" + echo " ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_dfc;" + echo " }" + echo " tme_m68k_write_memx${size}(ic);" echo " }" echo " else {" + echo " if (!TME_M68K_SEQUENCE_RESTARTING) {" + echo " ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_sfc;" + echo " }" + echo " tme_m68k_read_memx${size}(ic);" if test ${size} != 32; then echo " if (ireg >= TME_M68K_IREG_A0) {" echo " ic->tme_m68k_ireg_uint32(ireg) = " @@ -1040,6 +1090,12 @@ for size in 8 16 32 any; do ;; esac + # track statistics: + echo "" + echo "#ifdef _TME_M68K_STATS" + echo " ic->tme_m68k_stats.tme_m68k_stats_memory_total++;" + echo "#endif /* _TME_M68K_STATS */" + # if this is a write, log the value written: if test $name = write; then echo "" @@ -1369,7 +1425,7 @@ for size in 8 16 32 any; do echo " /* only byte transfers can be unaligned: */" echo " if (resid > sizeof(tme_uint8_t)" echo " && (linear_address & 1)) {" - echo " exception = TME_M68K_EXCEPTION_GROUP0_AERR;" + echo " exception = TME_M68K_EXCEPTION_AERR;" echo " break;" echo " }" echo "" @@ -1388,7 +1444,7 @@ for size in 8 16 32 any; do echo " /* an instruction fetch must be aligned: */" echo " if (flags & TME_M68K_BUS_CYCLE_FETCH) {" echo " if (linear_address & 1) {" - echo " exception = TME_M68K_EXCEPTION_GROUP0_AERR;" + echo " exception = TME_M68K_EXCEPTION_AERR;" echo " break;" echo " }" echo " assert(!(resid & 1));" @@ -1421,7 +1477,7 @@ for size in 8 16 32 any; do echo " if (!TME_M68K_TLB_OK_FAST_${capname}(tlb, function_code, linear_address, linear_address)" echo " || (rmw_rwlock != NULL" echo " && rmw_rwlock != tlb->tme_m68k_tlb_bus_rwlock)) {" - echo " exception = TME_M68K_EXCEPTION_GROUP0_BERR;" + echo " exception = TME_M68K_EXCEPTION_BERR;" echo " break;" echo " }" echo "" @@ -1457,11 +1513,20 @@ for size in 8 16 32 any; do echo " cycle.tme_bus_cycle_address = physical_address;" echo " }" echo "" + echo " /* otherwise, if we didn't get a bus error, but some" + echo " synchronous event has happened: */" + echo " else if (err == TME_BUS_CYCLE_SYNCHRONOUS_EVENT) {" + echo "" + echo " /* after the currently executing instruction finishes, check" + echo " for external resets, halts, or interrupts: */" + echo " ic->_tme_m68k_instruction_burst_remaining = 0;" + echo " }" + echo "" echo " /* otherwise, any other error might be a bus error: */" echo " else if (err != TME_OK) {" echo " err = tme_bus_tlb_fault(&tlb->tme_m68k_tlb_bus_tlb, &cycle, err);" echo " if (err != TME_OK) {" - echo " exception = TME_M68K_EXCEPTION_GROUP0_BERR;" + echo " exception = TME_M68K_EXCEPTION_BERR;" echo " break;" echo " }" echo " }" @@ -1802,8 +1867,9 @@ for _sign in u s; do echo " dividend = (tme_${sign}int${large}_t) ic->tme_m68k_ireg_${sign}int32(ireg_dq);" echo " divisor = TME_M68K_INSN_OP1(tme_${sign}int${small}_t);" echo " if (divisor == 0) {" + echo " ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;" echo " ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;" - echo " TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_GROUP2(5));" + echo " TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0));" echo " }" echo ""