--- tme/ic/m68k/m68k-insns-auto.c 2018/04/24 16:37:52 1.1.1.1 +++ tme/ic/m68k/m68k-insns-auto.c 2018/04/24 16:40:20 1.1.1.3 @@ -1,5 +1,5 @@ /* automatically generated by m68k-insns-auto.sh, do not edit! */ -_TME_RCSID("$Id: m68k-insns-auto.c,v 1.1.1.1 2018/04/24 16:37:52 root Exp $"); +_TME_RCSID("$Id: m68k-insns-auto.c,v 1.1.1.3 2018/04/24 16:40:20 root Exp $"); #include "m68k-impl.h" @@ -534,7 +534,7 @@ TME_M68K_INSN(tme_m68k_bset8) TME_M68K_INSN(tme_m68k_asl8) { unsigned int count; - tme_uint8_t sign_bits; + tme_uint8_t sign_bits, sign_bits_mask; tme_uint8_t res; tme_uint8_t flags; @@ -553,27 +553,28 @@ TME_M68K_INSN(tme_m68k_asl8) shifting in order to generate V. in general, the idea is to get all of the bits that will ever - appear in the sign position into sign_bits; if sign_bits is - all-bits-one or all-bits zero, clear V, else set V. a good trick - is that ((sign_bits + 1) & sign_bits) is nonzero iff all of the - bits in sign_bits are the same. + appear in the sign position into sign_bits, with a mask in + sign_bits_mask. if (sign_bits & sign_bits_mask) is zero or + sign_bits_mask, clear V, else set V. - start by loading all of the operand into sign_bits. + start by loading the operand into sign_bits and setting + sign_bits_mask to all-bits-one. if the shift count is exactly 8 - 1, then all of the bits of the operand will appear in the sign position. if the shift count is less than 8 - 1, then some of the less significant bits of the operand will never appear in the - sign position, so we can shift them off of sign_bits now. + sign position, so we can shift sign_bits_mask to ignore them. if the shift count is greater than 8 - 1, then all of the bits in the operand, plus at least one zero bit, will appear in the sign position. the only way that the sign bit will never change during the shift is if the operand was zero to begin with. - we need to change sign_bits such that ((sign_bits + 1) & - sign_bits) will be zero iff the operand was zero to begin with. - the magic below does just that: */ + without any changes to sign_bits or sign_bits_mask, the final + test will always work, except when sign_bits is all-bits-one. + the magic below clears the least-significant bit of sign_bits + iff sign_bits is all-bits-one: */ sign_bits = res; if (63 > SHIFTMAX_INT8_T && count > 8) { @@ -584,16 +585,17 @@ TME_M68K_INSN(tme_m68k_asl8) flags *= TME_M68K_FLAG_C; flags |= (flags * TME_M68K_FLAG_X); res <<= 1; + sign_bits_mask = (tme_uint8_t) -1; if (count != 8 - 1) { if (count < 8) { - sign_bits >>= ((8 - 1) - count); + sign_bits_mask <<= ((8 - 1) - count); } else { - sign_bits |= (sign_bits << 1); - sign_bits &= -2; + sign_bits ^= !(sign_bits + 1); } } - if ((sign_bits + 1) & sign_bits) { + sign_bits &= sign_bits_mask; + if (sign_bits != 0 && sign_bits != sign_bits_mask) { flags |= TME_M68K_FLAG_V; } } @@ -633,13 +635,23 @@ TME_M68K_INSN(tme_m68k_asr8) if (count > 0) { if (63 > SHIFTMAX_INT8_T && count > 8) { - res = 0; + res = 0 - (res < 0); } +#ifdef SHIFTSIGNED_INT8_T res >>= (count - 1); +#else /* !SHIFTSIGNED_INT8_T */ + for (; --count > 0; ) { + res = (res & ~((tme_int8_t) 1)) / 2; + } +#endif /* !SHIFTSIGNED_INT8_T */ flags = (res & 1); flags *= TME_M68K_FLAG_C; flags |= (flags * TME_M68K_FLAG_X); +#ifdef SHIFTSIGNED_INT8_T res >>= 1; +#else /* !SHIFTSIGNED_INT8_T */ + res = (res & ~((tme_int8_t) 1)) / 2; +#endif /* !SHIFTSIGNED_INT8_T */ } /* store the result: */ @@ -994,11 +1006,38 @@ TME_M68K_INSN(tme_m68k_cas8) TME_M68K_INSN(tme_m68k_moves8) { int ireg; + unsigned int ea_reg; + unsigned int increment; + TME_M68K_INSN_PRIV; + TME_M68K_INSN_CANFAULT; ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4); + + /* we have to handle postincrement and predecrement ourselves: */ + if (!TME_M68K_SEQUENCE_RESTARTING) { + ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); + increment = TME_M68K_SIZE_8; + if (increment == TME_M68K_SIZE_8 && ea_reg == TME_M68K_IREG_A7) { + increment = TME_M68K_SIZE_16; + } + switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3)) { + case 3: ic->tme_m68k_ireg_uint32(ea_reg) += increment; break; + case 4: ic->_tme_m68k_ea_address = (ic->tme_m68k_ireg_uint32(ea_reg) -= increment); break; + default: break; + } + } + if (TME_M68K_INSN_SPECOP & TME_BIT(11)) { - ic->tme_m68k_ireg_memx8 = ic->tme_m68k_ireg_uint8(ireg << 2); + if (!TME_M68K_SEQUENCE_RESTARTING) { + ic->tme_m68k_ireg_memx8 = ic->tme_m68k_ireg_uint8(ireg << 2); + ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_dfc; + } + tme_m68k_write_memx8(ic); } else { + if (!TME_M68K_SEQUENCE_RESTARTING) { + ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_sfc; + } + tme_m68k_read_memx8(ic); if (ireg >= TME_M68K_IREG_A0) { ic->tme_m68k_ireg_uint32(ireg) = TME_EXT_S8_U32((tme_int8_t) ic->tme_m68k_ireg_memx8); @@ -1521,7 +1560,7 @@ TME_M68K_INSN(tme_m68k_movea16) TME_M68K_INSN(tme_m68k_asl16) { unsigned int count; - tme_uint16_t sign_bits; + tme_uint16_t sign_bits, sign_bits_mask; tme_uint16_t res; tme_uint8_t flags; @@ -1540,27 +1579,28 @@ TME_M68K_INSN(tme_m68k_asl16) shifting in order to generate V. in general, the idea is to get all of the bits that will ever - appear in the sign position into sign_bits; if sign_bits is - all-bits-one or all-bits zero, clear V, else set V. a good trick - is that ((sign_bits + 1) & sign_bits) is nonzero iff all of the - bits in sign_bits are the same. + appear in the sign position into sign_bits, with a mask in + sign_bits_mask. if (sign_bits & sign_bits_mask) is zero or + sign_bits_mask, clear V, else set V. - start by loading all of the operand into sign_bits. + start by loading the operand into sign_bits and setting + sign_bits_mask to all-bits-one. if the shift count is exactly 16 - 1, then all of the bits of the operand will appear in the sign position. if the shift count is less than 16 - 1, then some of the less significant bits of the operand will never appear in the - sign position, so we can shift them off of sign_bits now. + sign position, so we can shift sign_bits_mask to ignore them. if the shift count is greater than 16 - 1, then all of the bits in the operand, plus at least one zero bit, will appear in the sign position. the only way that the sign bit will never change during the shift is if the operand was zero to begin with. - we need to change sign_bits such that ((sign_bits + 1) & - sign_bits) will be zero iff the operand was zero to begin with. - the magic below does just that: */ + without any changes to sign_bits or sign_bits_mask, the final + test will always work, except when sign_bits is all-bits-one. + the magic below clears the least-significant bit of sign_bits + iff sign_bits is all-bits-one: */ sign_bits = res; if (63 > SHIFTMAX_INT16_T && count > 16) { @@ -1571,16 +1611,17 @@ TME_M68K_INSN(tme_m68k_asl16) flags *= TME_M68K_FLAG_C; flags |= (flags * TME_M68K_FLAG_X); res <<= 1; + sign_bits_mask = (tme_uint16_t) -1; if (count != 16 - 1) { if (count < 16) { - sign_bits >>= ((16 - 1) - count); + sign_bits_mask <<= ((16 - 1) - count); } else { - sign_bits |= (sign_bits << 1); - sign_bits &= -2; + sign_bits ^= !(sign_bits + 1); } } - if ((sign_bits + 1) & sign_bits) { + sign_bits &= sign_bits_mask; + if (sign_bits != 0 && sign_bits != sign_bits_mask) { flags |= TME_M68K_FLAG_V; } } @@ -1620,13 +1661,23 @@ TME_M68K_INSN(tme_m68k_asr16) if (count > 0) { if (63 > SHIFTMAX_INT16_T && count > 16) { - res = 0; + res = 0 - (res < 0); } +#ifdef SHIFTSIGNED_INT16_T res >>= (count - 1); +#else /* !SHIFTSIGNED_INT16_T */ + for (; --count > 0; ) { + res = (res & ~((tme_int16_t) 1)) / 2; + } +#endif /* !SHIFTSIGNED_INT16_T */ flags = (res & 1); flags *= TME_M68K_FLAG_C; flags |= (flags * TME_M68K_FLAG_X); +#ifdef SHIFTSIGNED_INT16_T res >>= 1; +#else /* !SHIFTSIGNED_INT16_T */ + res = (res & ~((tme_int16_t) 1)) / 2; +#endif /* !SHIFTSIGNED_INT16_T */ } /* store the result: */ @@ -1961,8 +2012,6 @@ TME_M68K_INSN(tme_m68k_movem_rm16) unsigned int ea_mode; tme_uint32_t addend; - TME_M68K_INSN_CANFAULT; - /* figure out what direction to move in, and where to start from: */ ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3); direction = 1; @@ -1978,6 +2027,9 @@ TME_M68K_INSN(tme_m68k_movem_rm16) /* do the transfer: */ mask = TME_M68K_INSN_SPECOP; + if (mask != 0) { + TME_M68K_INSN_CANFAULT; + } for (bit = 1; bit != 0; bit <<= 1) { if (mask & bit) { if (!TME_M68K_SEQUENCE_RESTARTING) { @@ -2042,8 +2094,6 @@ TME_M68K_INSN(tme_m68k_movem_mr16) unsigned int ea_mode; tme_uint32_t addend; - TME_M68K_INSN_CANFAULT; - /* figure out what direction to move in, and where to start from: */ ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3); direction = 1; @@ -2052,6 +2102,9 @@ TME_M68K_INSN(tme_m68k_movem_mr16) /* do the transfer: */ mask = TME_M68K_INSN_SPECOP; + if (mask != 0) { + TME_M68K_INSN_CANFAULT; + } for (bit = 1; bit != 0; bit <<= 1) { if (mask & bit) { tme_m68k_read_memx16(ic); @@ -2077,13 +2130,15 @@ TME_M68K_INSN(tme_m68k_chk16) { if (*((tme_int16_t *) _op0) < 0) { ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_N; + ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; - TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_GROUP2(6)); + TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK)); } if (*((tme_int16_t *) _op0) > *((tme_int16_t *) _op1)) { ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_N; + ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; - TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_GROUP2(6)); + TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK)); } TME_M68K_INSN_OK; } @@ -2151,7 +2206,7 @@ TME_M68K_INSN(tme_m68k_cas2_16) int ireg_dc, ireg_du; int do_write; tme_uint16_t specopx = ic->_tme_m68k_insn_specop; - tme_uint16_t specopy = ic->_tme_m68k_insn_specop2; + tme_uint16_t specopy = TME_M68K_INSN_OP0(tme_uint16_t); tme_uint32_t addrx; tme_uint32_t addry; @@ -2248,11 +2303,38 @@ TME_M68K_INSN(tme_m68k_cas2_16) TME_M68K_INSN(tme_m68k_moves16) { int ireg; + unsigned int ea_reg; + unsigned int increment; + TME_M68K_INSN_PRIV; + TME_M68K_INSN_CANFAULT; ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4); + + /* we have to handle postincrement and predecrement ourselves: */ + if (!TME_M68K_SEQUENCE_RESTARTING) { + ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); + increment = TME_M68K_SIZE_16; + if (increment == TME_M68K_SIZE_8 && ea_reg == TME_M68K_IREG_A7) { + increment = TME_M68K_SIZE_16; + } + switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3)) { + case 3: ic->tme_m68k_ireg_uint32(ea_reg) += increment; break; + case 4: ic->_tme_m68k_ea_address = (ic->tme_m68k_ireg_uint32(ea_reg) -= increment); break; + default: break; + } + } + if (TME_M68K_INSN_SPECOP & TME_BIT(11)) { - ic->tme_m68k_ireg_memx16 = ic->tme_m68k_ireg_uint16(ireg << 1); + if (!TME_M68K_SEQUENCE_RESTARTING) { + ic->tme_m68k_ireg_memx16 = ic->tme_m68k_ireg_uint16(ireg << 1); + ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_dfc; + } + tme_m68k_write_memx16(ic); } else { + if (!TME_M68K_SEQUENCE_RESTARTING) { + ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_sfc; + } + tme_m68k_read_memx16(ic); if (ireg >= TME_M68K_IREG_A0) { ic->tme_m68k_ireg_uint32(ireg) = TME_EXT_S16_U32((tme_int16_t) ic->tme_m68k_ireg_memx16); @@ -2837,7 +2919,7 @@ TME_M68K_INSN(tme_m68k_bset32) TME_M68K_INSN(tme_m68k_asl32) { unsigned int count; - tme_uint32_t sign_bits; + tme_uint32_t sign_bits, sign_bits_mask; tme_uint32_t res; tme_uint8_t flags; @@ -2856,27 +2938,28 @@ TME_M68K_INSN(tme_m68k_asl32) shifting in order to generate V. in general, the idea is to get all of the bits that will ever - appear in the sign position into sign_bits; if sign_bits is - all-bits-one or all-bits zero, clear V, else set V. a good trick - is that ((sign_bits + 1) & sign_bits) is nonzero iff all of the - bits in sign_bits are the same. + appear in the sign position into sign_bits, with a mask in + sign_bits_mask. if (sign_bits & sign_bits_mask) is zero or + sign_bits_mask, clear V, else set V. - start by loading all of the operand into sign_bits. + start by loading the operand into sign_bits and setting + sign_bits_mask to all-bits-one. if the shift count is exactly 32 - 1, then all of the bits of the operand will appear in the sign position. if the shift count is less than 32 - 1, then some of the less significant bits of the operand will never appear in the - sign position, so we can shift them off of sign_bits now. + sign position, so we can shift sign_bits_mask to ignore them. if the shift count is greater than 32 - 1, then all of the bits in the operand, plus at least one zero bit, will appear in the sign position. the only way that the sign bit will never change during the shift is if the operand was zero to begin with. - we need to change sign_bits such that ((sign_bits + 1) & - sign_bits) will be zero iff the operand was zero to begin with. - the magic below does just that: */ + without any changes to sign_bits or sign_bits_mask, the final + test will always work, except when sign_bits is all-bits-one. + the magic below clears the least-significant bit of sign_bits + iff sign_bits is all-bits-one: */ sign_bits = res; if (63 > SHIFTMAX_INT32_T && count > 32) { @@ -2887,16 +2970,17 @@ TME_M68K_INSN(tme_m68k_asl32) flags *= TME_M68K_FLAG_C; flags |= (flags * TME_M68K_FLAG_X); res <<= 1; + sign_bits_mask = (tme_uint32_t) -1; if (count != 32 - 1) { if (count < 32) { - sign_bits >>= ((32 - 1) - count); + sign_bits_mask <<= ((32 - 1) - count); } else { - sign_bits |= (sign_bits << 1); - sign_bits &= -2; + sign_bits ^= !(sign_bits + 1); } } - if ((sign_bits + 1) & sign_bits) { + sign_bits &= sign_bits_mask; + if (sign_bits != 0 && sign_bits != sign_bits_mask) { flags |= TME_M68K_FLAG_V; } } @@ -2936,13 +3020,23 @@ TME_M68K_INSN(tme_m68k_asr32) if (count > 0) { if (63 > SHIFTMAX_INT32_T && count > 32) { - res = 0; + res = 0 - (res < 0); } +#ifdef SHIFTSIGNED_INT32_T res >>= (count - 1); +#else /* !SHIFTSIGNED_INT32_T */ + for (; --count > 0; ) { + res = (res & ~((tme_int32_t) 1)) / 2; + } +#endif /* !SHIFTSIGNED_INT32_T */ flags = (res & 1); flags *= TME_M68K_FLAG_C; flags |= (flags * TME_M68K_FLAG_X); +#ifdef SHIFTSIGNED_INT32_T res >>= 1; +#else /* !SHIFTSIGNED_INT32_T */ + res = (res & ~((tme_int32_t) 1)) / 2; +#endif /* !SHIFTSIGNED_INT32_T */ } /* store the result: */ @@ -3291,8 +3385,6 @@ TME_M68K_INSN(tme_m68k_movem_rm32) unsigned int ea_mode; tme_uint32_t addend; - TME_M68K_INSN_CANFAULT; - /* figure out what direction to move in, and where to start from: */ ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3); direction = 1; @@ -3308,6 +3400,9 @@ TME_M68K_INSN(tme_m68k_movem_rm32) /* do the transfer: */ mask = TME_M68K_INSN_SPECOP; + if (mask != 0) { + TME_M68K_INSN_CANFAULT; + } for (bit = 1; bit != 0; bit <<= 1) { if (mask & bit) { if (!TME_M68K_SEQUENCE_RESTARTING) { @@ -3390,8 +3485,6 @@ TME_M68K_INSN(tme_m68k_movem_mr32) unsigned int ea_mode; tme_uint32_t addend; - TME_M68K_INSN_CANFAULT; - /* figure out what direction to move in, and where to start from: */ ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3); direction = 1; @@ -3400,6 +3493,9 @@ TME_M68K_INSN(tme_m68k_movem_mr32) /* do the transfer: */ mask = TME_M68K_INSN_SPECOP; + if (mask != 0) { + TME_M68K_INSN_CANFAULT; + } for (bit = 1; bit != 0; bit <<= 1) { if (mask & bit) { tme_m68k_read_memx32(ic); @@ -3425,13 +3521,15 @@ TME_M68K_INSN(tme_m68k_chk32) { if (*((tme_int32_t *) _op0) < 0) { ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_N; + ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; - TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_GROUP2(6)); + TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK)); } if (*((tme_int32_t *) _op0) > *((tme_int32_t *) _op1)) { ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_N; + ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; - TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_GROUP2(6)); + TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK)); } TME_M68K_INSN_OK; } @@ -3499,7 +3597,7 @@ TME_M68K_INSN(tme_m68k_cas2_32) int ireg_dc, ireg_du; int do_write; tme_uint16_t specopx = ic->_tme_m68k_insn_specop; - tme_uint16_t specopy = ic->_tme_m68k_insn_specop2; + tme_uint16_t specopy = TME_M68K_INSN_OP0(tme_uint16_t); tme_uint32_t addrx; tme_uint32_t addry; @@ -3596,11 +3694,38 @@ TME_M68K_INSN(tme_m68k_cas2_32) TME_M68K_INSN(tme_m68k_moves32) { int ireg; + unsigned int ea_reg; + unsigned int increment; + TME_M68K_INSN_PRIV; + TME_M68K_INSN_CANFAULT; ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4); + + /* we have to handle postincrement and predecrement ourselves: */ + if (!TME_M68K_SEQUENCE_RESTARTING) { + ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3); + increment = TME_M68K_SIZE_32; + if (increment == TME_M68K_SIZE_8 && ea_reg == TME_M68K_IREG_A7) { + increment = TME_M68K_SIZE_16; + } + switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3)) { + case 3: ic->tme_m68k_ireg_uint32(ea_reg) += increment; break; + case 4: ic->_tme_m68k_ea_address = (ic->tme_m68k_ireg_uint32(ea_reg) -= increment); break; + default: break; + } + } + if (TME_M68K_INSN_SPECOP & TME_BIT(11)) { - ic->tme_m68k_ireg_memx32 = ic->tme_m68k_ireg_uint32(ireg); + if (!TME_M68K_SEQUENCE_RESTARTING) { + ic->tme_m68k_ireg_memx32 = ic->tme_m68k_ireg_uint32(ireg); + ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_dfc; + } + tme_m68k_write_memx32(ic); } else { + if (!TME_M68K_SEQUENCE_RESTARTING) { + ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_sfc; + } + tme_m68k_read_memx32(ic); ic->tme_m68k_ireg_uint32(ireg) = ic->tme_m68k_ireg_memx32; } TME_M68K_INSN_OK; @@ -3614,6 +3739,10 @@ tme_m68k_read_memx8(struct tme_m68k *ic) tme_uint32_t linear_address = ic->_tme_m68k_ea_address; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* do the bus cycle(s) ourselves from emulator memory if we can. the emulator memory allocator and TLB filler must guarantee that all tme_m68k_tlb_emulator_off_read pointers be 32-bit @@ -3659,6 +3788,10 @@ tme_m68k_read_mem8(struct tme_m68k *ic, tme_uint32_t linear_address = ic->_tme_m68k_ea_address; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* do the bus cycle(s) ourselves from emulator memory if we can. the emulator memory allocator and TLB filler must guarantee that all tme_m68k_tlb_emulator_off_read pointers be 32-bit @@ -3704,6 +3837,10 @@ tme_m68k_write_memx8(struct tme_m68k *ic tme_uint32_t linear_address = ic->_tme_m68k_ea_address; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* log the value written: */ tme_m68k_verify_mem8(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx8, TME_BUS_CYCLE_WRITE); tme_m68k_log(ic, 1000, TME_OK, @@ -3749,6 +3886,10 @@ tme_m68k_write_mem8(struct tme_m68k *ic, tme_uint32_t linear_address = ic->_tme_m68k_ea_address; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* log the value written: */ tme_m68k_verify_mem8(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint8(ireg), TME_BUS_CYCLE_WRITE); tme_m68k_log(ic, 1000, TME_OK, @@ -3795,6 +3936,10 @@ tme_m68k_read_memx16(struct tme_m68k *ic tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address_first); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* do the bus cycle(s) ourselves from emulator memory if we can. the emulator memory allocator and TLB filler must guarantee that all tme_m68k_tlb_emulator_off_read pointers be 32-bit @@ -3849,6 +3994,10 @@ tme_m68k_read_mem16(struct tme_m68k *ic, tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address_first); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* do the bus cycle(s) ourselves from emulator memory if we can. the emulator memory allocator and TLB filler must guarantee that all tme_m68k_tlb_emulator_off_read pointers be 32-bit @@ -3904,6 +4053,10 @@ tme_m68k_fetch16(struct tme_m68k *ic, tm struct tme_m68k_tlb *tlb = TME_ATOMIC_READ(struct tme_m68k_tlb *, ic->_tme_m68k_itlb); unsigned int insn_buffer_off = TME_ALIGN(ic->_tme_m68k_insn_buffer_off, sizeof(tme_uint16_t)); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* do the bus cycle(s) ourselves from emulator memory if we can. the emulator memory allocator and TLB filler must guarantee that all tme_m68k_tlb_emulator_off_read pointers be 32-bit @@ -3960,6 +4113,10 @@ tme_m68k_pop16(struct tme_m68k *ic, tme_ tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address_first); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* do the bus cycle(s) ourselves from emulator memory if we can. the emulator memory allocator and TLB filler must guarantee that all tme_m68k_tlb_emulator_off_read pointers be 32-bit @@ -4017,6 +4174,10 @@ tme_m68k_write_memx16(struct tme_m68k *i tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address_first); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* log the value written: */ tme_m68k_verify_mem16(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx16, TME_BUS_CYCLE_WRITE); tme_m68k_log(ic, 1000, TME_OK, @@ -4071,6 +4232,10 @@ tme_m68k_write_mem16(struct tme_m68k *ic tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address_first); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* log the value written: */ tme_m68k_verify_mem16(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint16(ireg), TME_BUS_CYCLE_WRITE); tme_m68k_log(ic, 1000, TME_OK, @@ -4125,6 +4290,10 @@ tme_m68k_push16(struct tme_m68k *ic, tme tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address_first); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* log the value written: */ tme_m68k_verify_mem16(ic, function_code, linear_address_first, value, TME_BUS_CYCLE_WRITE); tme_m68k_log(ic, 1000, TME_OK, @@ -4182,6 +4351,10 @@ tme_m68k_read_memx32(struct tme_m68k *ic tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address_first); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* do the bus cycle(s) ourselves from emulator memory if we can. the emulator memory allocator and TLB filler must guarantee that all tme_m68k_tlb_emulator_off_read pointers be 32-bit @@ -4265,6 +4438,10 @@ tme_m68k_read_mem32(struct tme_m68k *ic, tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address_first); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* do the bus cycle(s) ourselves from emulator memory if we can. the emulator memory allocator and TLB filler must guarantee that all tme_m68k_tlb_emulator_off_read pointers be 32-bit @@ -4349,6 +4526,10 @@ tme_m68k_fetch32(struct tme_m68k *ic, tm struct tme_m68k_tlb *tlb = TME_ATOMIC_READ(struct tme_m68k_tlb *, ic->_tme_m68k_itlb); unsigned int insn_buffer_off = TME_ALIGN(ic->_tme_m68k_insn_buffer_off, sizeof(tme_uint32_t)); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* do the bus cycle(s) ourselves from emulator memory if we can. the emulator memory allocator and TLB filler must guarantee that all tme_m68k_tlb_emulator_off_read pointers be 32-bit @@ -4434,6 +4615,10 @@ tme_m68k_pop32(struct tme_m68k *ic, tme_ tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address_first); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* do the bus cycle(s) ourselves from emulator memory if we can. the emulator memory allocator and TLB filler must guarantee that all tme_m68k_tlb_emulator_off_read pointers be 32-bit @@ -4520,6 +4705,10 @@ tme_m68k_write_memx32(struct tme_m68k *i tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address_first); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* log the value written: */ tme_m68k_verify_mem32(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx32, TME_BUS_CYCLE_WRITE); tme_m68k_log(ic, 1000, TME_OK, @@ -4600,6 +4789,10 @@ tme_m68k_write_mem32(struct tme_m68k *ic tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address_first); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* log the value written: */ tme_m68k_verify_mem32(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint32(ireg), TME_BUS_CYCLE_WRITE); tme_m68k_log(ic, 1000, TME_OK, @@ -4680,6 +4873,10 @@ tme_m68k_push32(struct tme_m68k *ic, tme tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address_first); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* log the value written: */ tme_m68k_verify_mem32(ic, function_code, linear_address_first, value, TME_BUS_CYCLE_WRITE); tme_m68k_log(ic, 1000, TME_OK, @@ -4763,6 +4960,10 @@ tme_m68k_read_mem(struct tme_m68k *ic, t tme_uint32_t linear_address_last = linear_address_first + count - 1; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address_first); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* do the bus cycle(s) ourselves from emulator memory if we can. the emulator memory allocator and TLB filler must guarantee that all tme_m68k_tlb_emulator_off_read pointers be 32-bit @@ -4902,7 +5103,7 @@ tme_m68k_read(struct tme_m68k *ic, /* only byte transfers can be unaligned: */ if (resid > sizeof(tme_uint8_t) && (linear_address & 1)) { - exception = TME_M68K_EXCEPTION_GROUP0_AERR; + exception = TME_M68K_EXCEPTION_AERR; break; } @@ -4920,7 +5121,7 @@ tme_m68k_read(struct tme_m68k *ic, /* an instruction fetch must be aligned: */ if (flags & TME_M68K_BUS_CYCLE_FETCH) { if (linear_address & 1) { - exception = TME_M68K_EXCEPTION_GROUP0_AERR; + exception = TME_M68K_EXCEPTION_AERR; break; } assert(!(resid & 1)); @@ -4951,7 +5152,7 @@ tme_m68k_read(struct tme_m68k *ic, if (!TME_M68K_TLB_OK_FAST_READ(tlb, function_code, linear_address, linear_address) || (rmw_rwlock != NULL && rmw_rwlock != tlb->tme_m68k_tlb_bus_rwlock)) { - exception = TME_M68K_EXCEPTION_GROUP0_BERR; + exception = TME_M68K_EXCEPTION_BERR; break; } @@ -4985,11 +5186,20 @@ tme_m68k_read(struct tme_m68k *ic, cycle.tme_bus_cycle_address = physical_address; } + /* otherwise, if we didn't get a bus error, but some + synchronous event has happened: */ + else if (err == TME_BUS_CYCLE_SYNCHRONOUS_EVENT) { + + /* after the currently executing instruction finishes, check + for external resets, halts, or interrupts: */ + ic->_tme_m68k_instruction_burst_remaining = 0; + } + /* otherwise, any other error might be a bus error: */ else if (err != TME_OK) { err = tme_bus_tlb_fault(&tlb->tme_m68k_tlb_bus_tlb, &cycle, err); if (err != TME_OK) { - exception = TME_M68K_EXCEPTION_GROUP0_BERR; + exception = TME_M68K_EXCEPTION_BERR; break; } } @@ -5037,6 +5247,10 @@ tme_m68k_write_mem(struct tme_m68k *ic, tme_uint32_t linear_address_last = linear_address_first + count - 1; struct tme_m68k_tlb *tlb = TME_M68K_TLB_ENTRY(ic, function_code, linear_address_first); +#ifdef _TME_M68K_STATS + ic->tme_m68k_stats.tme_m68k_stats_memory_total++; +#endif /* _TME_M68K_STATS */ + /* log the value written: */ tme_m68k_verify_mem_any(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, buffer, count, TME_BUS_CYCLE_WRITE); tme_m68k_log_start(ic, 1000, TME_OK) { @@ -5176,7 +5390,7 @@ tme_m68k_write(struct tme_m68k *ic, /* only byte transfers can be unaligned: */ if (resid > sizeof(tme_uint8_t) && (linear_address & 1)) { - exception = TME_M68K_EXCEPTION_GROUP0_AERR; + exception = TME_M68K_EXCEPTION_AERR; break; } @@ -5216,7 +5430,7 @@ tme_m68k_write(struct tme_m68k *ic, if (!TME_M68K_TLB_OK_FAST_WRITE(tlb, function_code, linear_address, linear_address) || (rmw_rwlock != NULL && rmw_rwlock != tlb->tme_m68k_tlb_bus_rwlock)) { - exception = TME_M68K_EXCEPTION_GROUP0_BERR; + exception = TME_M68K_EXCEPTION_BERR; break; } @@ -5250,11 +5464,20 @@ tme_m68k_write(struct tme_m68k *ic, cycle.tme_bus_cycle_address = physical_address; } + /* otherwise, if we didn't get a bus error, but some + synchronous event has happened: */ + else if (err == TME_BUS_CYCLE_SYNCHRONOUS_EVENT) { + + /* after the currently executing instruction finishes, check + for external resets, halts, or interrupts: */ + ic->_tme_m68k_instruction_burst_remaining = 0; + } + /* otherwise, any other error might be a bus error: */ else if (err != TME_OK) { err = tme_bus_tlb_fault(&tlb->tme_m68k_tlb_bus_tlb, &cycle, err); if (err != TME_OK) { - exception = TME_M68K_EXCEPTION_GROUP0_BERR; + exception = TME_M68K_EXCEPTION_BERR; break; } } @@ -5596,8 +5819,9 @@ TME_M68K_INSN(tme_m68k_divu) dividend = (tme_uint32_t) ic->tme_m68k_ireg_uint32(ireg_dq); divisor = TME_M68K_INSN_OP1(tme_uint16_t); if (divisor == 0) { + ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; - TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_GROUP2(5)); + TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0)); } /* do the division: */ @@ -5622,9 +5846,9 @@ TME_M68K_INSN(tme_m68k_divu) TME_M68K_INSN(tme_m68k_mulul) { -#ifndef HAVE_UINT64_T +#ifndef TME_HAVE_INT64_T abort(); -#else /* HAVE_UINT64_T */ +#else /* TME_HAVE_INT64_T */ unsigned int flag_v; int ireg_dh; int ireg_dl; @@ -5651,18 +5875,18 @@ TME_M68K_INSN(tme_m68k_mulul) flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; if (((tme_int64_t) res) < 0) flags |= TME_M68K_FLAG_N; if (res == 0) flags |= TME_M68K_FLAG_Z; - if (res > 0xffffffff) flags |= flag_v; + if (res > 0xffffffffUL) flags |= flag_v; ic->tme_m68k_ireg_ccr = flags; TME_M68K_INSN_OK; -#endif /* HAVE_UINT64_T */ +#endif /* TME_HAVE_INT64_T */ } TME_M68K_INSN(tme_m68k_divul) { -#ifndef HAVE_UINT64_T +#ifndef TME_HAVE_INT64_T abort(); -#else /* HAVE_UINT64_T */ +#else /* TME_HAVE_INT64_T */ int ireg_dr; int ireg_dq; tme_uint64_t dividend, quotient; @@ -5683,8 +5907,9 @@ TME_M68K_INSN(tme_m68k_divul) dividend = (tme_uint64_t) ic->tme_m68k_ireg_uint32(ireg_dq); divisor = TME_M68K_INSN_OP1(tme_uint32_t); if (divisor == 0) { + ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; - TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_GROUP2(5)); + TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0)); } /* do the division: */ @@ -5693,7 +5918,7 @@ TME_M68K_INSN(tme_m68k_divul) /* set the flags and return the quotient and remainder: */ flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; - if (quotient > 0xffffffff) { + if (quotient > 0xffffffffUL) { flags |= TME_M68K_FLAG_V; } else { @@ -5707,7 +5932,7 @@ TME_M68K_INSN(tme_m68k_divul) ic->tme_m68k_ireg_ccr = flags; TME_M68K_INSN_OK; -#endif /* HAVE_UINT64_T */ +#endif /* TME_HAVE_INT64_T */ } TME_M68K_INSN(tme_m68k_muls) @@ -5749,8 +5974,9 @@ TME_M68K_INSN(tme_m68k_divs) dividend = (tme_int32_t) ic->tme_m68k_ireg_int32(ireg_dq); divisor = TME_M68K_INSN_OP1(tme_int16_t); if (divisor == 0) { + ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; - TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_GROUP2(5)); + TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0)); } /* do the division: */ @@ -5759,7 +5985,7 @@ TME_M68K_INSN(tme_m68k_divs) /* set the flags and return the quotient and remainder: */ flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; - if (quotient > 0xffff || quotient < -32768) { + if (quotient > 0x7fff || quotient < -32768) { flags |= TME_M68K_FLAG_V; } else { @@ -5775,9 +6001,9 @@ TME_M68K_INSN(tme_m68k_divs) TME_M68K_INSN(tme_m68k_mulsl) { -#ifndef HAVE_UINT64_T +#ifndef TME_HAVE_INT64_T abort(); -#else /* HAVE_UINT64_T */ +#else /* TME_HAVE_INT64_T */ unsigned int flag_v; int ireg_dh; int ireg_dl; @@ -5804,18 +6030,18 @@ TME_M68K_INSN(tme_m68k_mulsl) flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; if (((tme_int64_t) res) < 0) flags |= TME_M68K_FLAG_N; if (res == 0) flags |= TME_M68K_FLAG_Z; - if (res > 0xffffffff || res < -2147483648) flags |= flag_v; + if (res > 0x7fffffffL || res < ((0L - 0x7fffffffL) - 1L)) flags |= flag_v; ic->tme_m68k_ireg_ccr = flags; TME_M68K_INSN_OK; -#endif /* HAVE_UINT64_T */ +#endif /* TME_HAVE_INT64_T */ } TME_M68K_INSN(tme_m68k_divsl) { -#ifndef HAVE_UINT64_T +#ifndef TME_HAVE_INT64_T abort(); -#else /* HAVE_UINT64_T */ +#else /* TME_HAVE_INT64_T */ int ireg_dr; int ireg_dq; tme_int64_t dividend, quotient; @@ -5836,8 +6062,9 @@ TME_M68K_INSN(tme_m68k_divsl) dividend = (tme_int64_t) ic->tme_m68k_ireg_int32(ireg_dq); divisor = TME_M68K_INSN_OP1(tme_int32_t); if (divisor == 0) { + ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; - TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_GROUP2(5)); + TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0)); } /* do the division: */ @@ -5846,7 +6073,7 @@ TME_M68K_INSN(tme_m68k_divsl) /* set the flags and return the quotient and remainder: */ flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X; - if (quotient > 0xffffffff || quotient < -2147483648) { + if (quotient > 0x7fffffffL || quotient < ((0L - 0x7fffffffL) - 1L)) { flags |= TME_M68K_FLAG_V; } else { @@ -5860,7 +6087,7 @@ TME_M68K_INSN(tme_m68k_divsl) ic->tme_m68k_ireg_ccr = flags; TME_M68K_INSN_OK; -#endif /* HAVE_UINT64_T */ +#endif /* TME_HAVE_INT64_T */ } /* automatically generated by m68k-misc-auto.sh, do not edit! */