--- tme/ic/m68k/m68k-insns-auto.c 2018/04/24 16:37:52 1.1 +++ tme/ic/m68k/m68k-insns-auto.c 2018/04/24 16:39:00 1.1.1.2 @@ -1,5 +1,5 @@ /* automatically generated by m68k-insns-auto.sh, do not edit! */ -_TME_RCSID("$Id: m68k-insns-auto.c,v 1.1 2018/04/24 16:37:52 root Exp $"); +_TME_RCSID("$Id: m68k-insns-auto.c,v 1.1.1.2 2018/04/24 16:39:00 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; } } @@ -1521,7 +1523,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 +1542,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 +1574,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; } } @@ -1961,8 +1965,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 +1980,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 +2047,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 +2055,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); @@ -2837,7 +2843,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 +2862,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 +2894,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; } } @@ -3291,8 +3299,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 +3314,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 +3399,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 +3407,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); @@ -5622,9 +5632,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 +5661,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; @@ -5693,7 +5703,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 +5717,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) @@ -5759,7 +5769,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 +5785,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 +5814,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; @@ -5846,7 +5856,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 +5870,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! */