3b2: unsigned addition overflow

- Integer addition of unsigned types could fail to set the
  overflow flag, leading to errors in the SVR3 floating point
  emulation library that rely on the overflow flag to detect
  carry out of high bit on unsigned addition. This change
  will correctly set the V flag if the high bit should be
  carried out on an add.
This commit is contained in:
Seth Morabito 2019-06-29 19:40:57 -07:00
parent 571c8f96a5
commit dd715e609e

View file

@ -3690,19 +3690,29 @@ static SIM_INLINE void add(t_uint64 a, t_uint64 b, operand *dst)
switch(op_type(dst)) { switch(op_type(dst)) {
case WD: case WD:
cpu_set_c_flag(result > WORD_MASK);
cpu_set_v_flag(((a ^ ~b) & (a ^ result)) & WD_MSB);
break;
case UW: case UW:
cpu_set_c_flag(result > WORD_MASK); cpu_set_c_flag(result > WORD_MASK);
cpu_set_v_flag(!! (((a ^ ~b) & (a ^ result)) & WD_MSB)); cpu_set_v_flag(result > WORD_MASK);
break; break;
case HW: case HW:
case UH:
cpu_set_c_flag(result > HALF_MASK); cpu_set_c_flag(result > HALF_MASK);
cpu_set_v_flag(((a ^ ~b) & (a ^ result)) & HW_MSB); cpu_set_v_flag(((a ^ ~b) & (a ^ result)) & HW_MSB);
break; break;
case UH:
cpu_set_c_flag(result > HALF_MASK);
cpu_set_v_flag(result > HALF_MASK);
break;
case BT: case BT:
cpu_set_c_flag(result > BYTE_MASK);
cpu_set_v_flag(result > BYTE_MASK);
break;
case SB: case SB:
cpu_set_c_flag(result > BYTE_MASK); cpu_set_c_flag(result > BYTE_MASK);
cpu_set_v_flag(((a ^ ~b) & (a ^ result)) & BT_MSB); cpu_set_v_flag(((a ^ ~b) & (a ^ result)) & BT_MSB);
break;
} }
} }