Commit d7295dbc authored by sagnowski's avatar sagnowski
Browse files

Add configurable overflow handling

parent 6936ad5b
Loading
Loading
Loading
Loading
+74 −25
Original line number Diff line number Diff line
@@ -156,11 +156,60 @@ static Word16 saturate (Word32 L_var1);
Flag BASOP_Overflow = 0;
Flag BASOP_Carry = 0;
*/
#if defined BASOP_NOGLOB_DEV_PRINT || defined BASOP_NOGLOB_DEV_ABORT
int overflow_warning_enable=1, overflow_warning_disable_counter=0;
int overflow_error_enable=0;
#endif
#else /* BASOP_NOGLOB */
Flag Overflow = 0;
Flag Carry = 0;
#endif /* BASOP_NOGLOB */

#ifdef BASOP_NOGLOB
#if defined BASOP_NOGLOB_DEV_ABORT
#define BASOP_TRIGGER_OVERFLOW_ERROR_OR_WARNING(error_enable, warning_enable) if ((error_enable) || (warning_enable)) { assert(0); }
#elif defined BASOP_NOGLOB_DEV_PRINT
#define BASOP_TRIGGER_OVERFLOW_ERROR_OR_WARNING(error_enable, warning_enable) if (error_enable) { print_basop_noglob_error(); } else if (warning_enable) { print_basop_noglob_warning(); }
#else
#define BASOP_TRIGGER_OVERFLOW_ERROR_OR_WARNING(error_enable, warning_enable) (void)0; /* noop */
#endif
void set_overflow(Flag *overflow) { if (overflow) *overflow = 1; else { BASOP_TRIGGER_OVERFLOW_ERROR_OR_WARNING(overflow_error_enable, overflow_warning_enable); } }
void unset_overflow(Flag* overflow) { if (overflow) *overflow = 0;  else { BASOP_TRIGGER_OVERFLOW_ERROR_OR_WARNING(overflow_error_enable, overflow_warning_enable); } }
void set_carry(Flag *carry) { if (carry) *carry = 1; else { BASOP_TRIGGER_OVERFLOW_ERROR_OR_WARNING(overflow_error_enable, overflow_warning_enable); } }
void unset_carry(Flag* carry) { if (carry) *carry = 0; else { BASOP_TRIGGER_OVERFLOW_ERROR_OR_WARNING(overflow_error_enable, overflow_warning_enable); } }
Flag get_carry(Flag* carry) { if (carry) return *carry; else { BASOP_TRIGGER_OVERFLOW_ERROR_OR_WARNING(overflow_error_enable, overflow_warning_enable); } return 0; }

#ifdef BASOP_NOGLOB_DEV_PRINT
#include <stdio.h>
#if  defined(__unix__) || defined(__unix) || defined(__APPLE__)
#include <execinfo.h>
void print_stack(void) {
  void *call_stack[200];
  int i;
  int num_frames = backtrace(call_stack, 200);
  char **strs = backtrace_symbols(call_stack, num_frames);
  for (i = 0; i < num_frames; ++i) {
    printf("[BASOP] %s\n", strs[i]);
  }
  free(strs);
}
#else
void print_stack(void) {
  printf("[BASOP] <call stack would be here> - printing call stack currently only supported on UNIX");
}
#endif

void print_basop_noglob_warning(void) {
  printf("[BASOP] Overflow occured. Call stack:\n");
  print_stack(); /* TODO(sgi): printStack from LC3 does not work out of the box */
}
void print_basop_noglob_error(void) {
  printf("[BASOP] Overflow error occured. Call stack:\n");
  print_stack();
}
#endif
#endif /* BASOP_NOGLOB */


/*___________________________________________________________________________
 |                                                                           |
@@ -203,14 +252,14 @@ static Word16 saturate (Word32 L_var1) {

  if (L_var1 > 0X00007fffL) {
#ifdef BASOP_NOGLOB
    set_flag (Overflow);
    set_overflow (Overflow);
#else /* BASOP_NOGLOB */
    Overflow = 1;
#endif /* BASOP_NOGLOB */
    var_out = MAX_16;
  } else if (L_var1 < (Word32) 0xffff8000L) {
#ifdef BASOP_NOGLOB
    set_flag (Overflow);
    set_overflow (Overflow);
#else /* BASOP_NOGLOB */
    Overflow = 1;
#endif /* BASOP_NOGLOB */
@@ -457,7 +506,7 @@ Word16 shl (Word16 var1, Word16 var2) {

    if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result))) {
#ifdef BASOP_NOGLOB
      set_flag (Overflow);
      set_overflow (Overflow);
#else /* BASOP_NOGLOB */
      Overflow = 1;
#endif /* BASOP_NOGLOB */
@@ -678,7 +727,7 @@ Word32 L_mult (Word16 var1, Word16 var2) {
    L_var_out *= 2;
  } else {
#ifdef BASOP_NOGLOB
    set_flag (Overflow);
    set_overflow (Overflow);
#else /* BASOP_NOGLOB */
    Overflow = 1;
#endif /* BASOP_NOGLOB */
@@ -1204,7 +1253,7 @@ Word32 L_add (Word32 L_var1, Word32 L_var2) {
    if ((L_var_out ^ L_var1) & MIN_32) {
      L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;
#ifdef BASOP_NOGLOB
      set_flag (Overflow);
      set_overflow (Overflow);
#else /* BASOP_NOGLOB */
      Overflow = 1;
#endif /* BASOP_NOGLOB */
@@ -1267,7 +1316,7 @@ Word32 L_sub (Word32 L_var1, Word32 L_var2) {
    if ((L_var_out ^ L_var1) & MIN_32) {
      L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;
#ifdef BASOP_NOGLOB
      set_flag (Overflow);
      set_overflow (Overflow);
#else /* BASOP_NOGLOB */
      Overflow = 1;
#endif /* BASOP_NOGLOB */
@@ -1341,7 +1390,7 @@ Word32 L_add_c (Word32 L_var1, Word32 L_var2) {
  Flag carry_int = 0;

#ifdef BASOP_NOGLOB
  L_var_out = L_var1 + L_var2 + get_flag (Carry);
  L_var_out = L_var1 + L_var2 + get_carry (Carry);
#else /* BASOP_NOGLOB */
  L_var_out = L_var1 + L_var2 + Carry;
#endif /* BASOP_NOGLOB */
@@ -1350,7 +1399,7 @@ Word32 L_add_c (Word32 L_var1, Word32 L_var2) {

  if ((L_var1 > 0) && (L_var2 > 0) && (L_test < 0)) {
#ifdef BASOP_NOGLOB
    set_flag (Overflow);
    set_overflow (Overflow);
#else /* BASOP_NOGLOB */
    Overflow = 1;
#endif /* BASOP_NOGLOB */
@@ -1359,14 +1408,14 @@ Word32 L_add_c (Word32 L_var1, Word32 L_var2) {
    if ((L_var1 < 0) && (L_var2 < 0)) {
      if (L_test >= 0) {
#ifdef BASOP_NOGLOB
        set_flag (Overflow);
        set_overflow (Overflow);
#else /* BASOP_NOGLOB */
        Overflow = 1;
#endif /* BASOP_NOGLOB */
        carry_int = 1;
      } else {
#ifdef BASOP_NOGLOB
        unset_flag (Overflow);
        unset_overflow (Overflow);
#else /* BASOP_NOGLOB */
        Overflow = 0;
#endif /* BASOP_NOGLOB */
@@ -1375,14 +1424,14 @@ Word32 L_add_c (Word32 L_var1, Word32 L_var2) {
    } else {
      if (((L_var1 ^ L_var2) < 0) && (L_test >= 0)) {
#ifdef BASOP_NOGLOB
        unset_flag (Overflow);
        unset_overflow (Overflow);
#else /* BASOP_NOGLOB */
        Overflow = 0;
#endif /* BASOP_NOGLOB */
        carry_int = 1;
      } else {
#ifdef BASOP_NOGLOB
        unset_flag (Overflow);
        unset_overflow (Overflow);
#else /* BASOP_NOGLOB */
        Overflow = 0;
#endif /* BASOP_NOGLOB */
@@ -1392,14 +1441,14 @@ Word32 L_add_c (Word32 L_var1, Word32 L_var2) {
  }

#ifdef BASOP_NOGLOB
  if (get_flag (Carry)) {
  if (get_carry (Carry)) {
#else /* BASOP_NOGLOB */
  if (Carry) {
#endif /* BASOP_NOGLOB */
    if (L_test == MAX_32) {
#ifdef BASOP_NOGLOB
      set_flag (Overflow);
      carry_int ? set_flag (Carry) : unset_flag (Carry);
      set_overflow (Overflow);
      carry_int ? set_carry (Carry) : unset_carry (Carry);
#else /* BASOP_NOGLOB */
      Overflow = 1;
      Carry = carry_int;
@@ -1407,13 +1456,13 @@ Word32 L_add_c (Word32 L_var1, Word32 L_var2) {
    } else {
      if (L_test == (Word32) 0xFFFFFFFFL) {
#ifdef BASOP_NOGLOB
        set_flag (Carry);
        set_carry (Carry);
#else /* BASOP_NOGLOB */
        Carry = 1;
#endif /* BASOP_NOGLOB */
      } else {
#ifdef BASOP_NOGLOB
        carry_int ? set_flag (Carry) : unset_flag (Carry);
        carry_int ? set_carry (Carry) : unset_carry (Carry);
#else /* BASOP_NOGLOB */
        Carry = carry_int;
#endif /* BASOP_NOGLOB */
@@ -1421,7 +1470,7 @@ Word32 L_add_c (Word32 L_var1, Word32 L_var2) {
    }
  } else {
#ifdef BASOP_NOGLOB
    carry_int ? set_flag (Carry) : unset_flag (Carry);
    carry_int ? set_carry (Carry) : unset_carry (Carry);
#else /* BASOP_NOGLOB */
    Carry = carry_int;
#endif /* BASOP_NOGLOB */
@@ -1495,8 +1544,8 @@ Word32 L_sub_c (Word32 L_var1, Word32 L_var2) {
  Flag carry_int = 0;

#ifdef BASOP_NOGLOB
  if (get_flag (Carry)) {
    unset_flag (Carry);
  if (get_carry (Carry)) {
    unset_carry (Carry);
#else /* BASOP_NOGLOB */
  if (Carry) {
    Carry = 0;
@@ -1514,7 +1563,7 @@ Word32 L_sub_c (Word32 L_var1, Word32 L_var2) {
      L_var_out = L_var1 - L_var2;
      if (L_var1 > 0L) {
#ifdef BASOP_NOGLOB
        unset_flag (Carry);
        unset_carry (Carry);
#else /* BASOP_NOGLOB */
        Overflow = 1;
        Carry = 0;
@@ -1543,14 +1592,14 @@ Word32 L_sub_c (Word32 L_var1, Word32 L_var2) {
    }
    if (L_test == MIN_32) {
#ifdef BASOP_NOGLOB
      carry_int ? set_flag (Carry) : unset_flag (Carry);
      carry_int ? set_carry (Carry) : unset_carry (Carry);
#else /* BASOP_NOGLOB */
      Overflow = 1;
      Carry = carry_int;
#endif /* BASOP_NOGLOB */
    } else {
#ifdef BASOP_NOGLOB
      carry_int ? set_flag (Carry) : unset_flag (Carry);
      carry_int ? set_carry (Carry) : unset_carry (Carry);
#else /* BASOP_NOGLOB */
      Carry = carry_int;
#endif /* BASOP_NOGLOB */
@@ -1730,7 +1779,7 @@ Word32 L_shl (Word32 L_var1, Word16 var2) {
    for (; var2 > 0; var2--) {
      if (L_var1 > (Word32) 0X3fffffffL) {
#ifdef BASOP_NOGLOB
        set_flag (Overflow);
        set_overflow (Overflow);
#else /* BASOP_NOGLOB */
        Overflow = 1;
#endif /* BASOP_NOGLOB */
@@ -1739,7 +1788,7 @@ Word32 L_shl (Word32 L_var1, Word16 var2) {
      } else {
        if (L_var1 < (Word32) 0xc0000000L) {
#ifdef BASOP_NOGLOB
          set_flag (Overflow);
          set_overflow (Overflow);
#else /* BASOP_NOGLOB */
          Overflow = 1;
#endif /* BASOP_NOGLOB */
+42 −3
Original line number Diff line number Diff line
@@ -61,15 +61,52 @@
extern Flag BASOP_Overflow, BASOP_Overflow2;
extern Flag BASOP_Carry;
*/
#if defined BASOP_NOGLOB_DEV_PRINT || defined BASOP_NOGLOB_DEV_ABORT
extern int overflow_count;
extern int overflow_warning_enable, overflow_warning_disable_counter;
extern int overflow_error_enable;

#define BASOP_SATURATE_WARNING_ON  {\
    overflow_warning_disable_counter--;\
    if (overflow_warning_disable_counter < 0) overflow_warning_disable_counter = 0;\
    if (overflow_warning_disable_counter == 0) {\
        overflow_warning_enable=1;\
    }\
}
#define BASOP_SATURATE_WARNING_OFF {\
    overflow_warning_enable=0;\
    overflow_warning_disable_counter++;\
}
#define BASOP_SATURATE_ERROR_ON  {\
    overflow_error_enable=1;\
}
#define BASOP_SATURATE_ERROR_OFF {\
    overflow_error_enable=0;\
}

#ifdef BASOP_NOGLOB_DEV_PRINT
void print_basop_noglob_warning(void);
void print_basop_noglob_error(void);
#endif
#else
#define BASOP_SATURATE_WARNING_ON
#define BASOP_SATURATE_WARNING_OFF
#define BASOP_SATURATE_ERROR_ON
#define BASOP_SATURATE_ERROR_OFF
#endif

#else /* BASOP_NOGLOB */
extern Flag Overflow, Overflow2;
extern Flag Carry;
#endif /* BASOP_NOGLOB */


#ifndef BASOP_NOGLOB
#define BASOP_SATURATE_WARNING_ON
#define BASOP_SATURATE_WARNING_OFF
#define BASOP_SATURATE_ERROR_ON
#define BASOP_SATURATE_ERROR_OFF
#endif
#define BASOP_CHECK()

#define MAX_32 (Word32)0x7fffffffL
@@ -79,9 +116,11 @@ extern Flag Carry;
#define MIN_16 (Word16)0x8000

#ifdef BASOP_NOGLOB
static inline void set_flag(Flag* flag) { if (flag) *flag = 1; else assert(0); }
static inline void unset_flag(Flag* flag) { if (flag) *flag = 0; else assert(0); }
static inline Flag get_flag(Flag* flag) { if (flag) return *flag; else assert(0); }
void set_overflow(Flag *overflow);
void unset_overflow(Flag* overflow);
void set_carry(Flag *carry);
void unset_carry(Flag* carry);
Flag get_carry(Flag* carry);
#endif /* BASOP_NOGLOB */

/*___________________________________________________________________________
+8 −8
Original line number Diff line number Diff line
@@ -151,7 +151,7 @@ Word40 L40_shl (Word40 L40_var1, Word16 var2) {
    for (; var2 > 0; var2--) {
      if (L40_var_out > 0x003fffffffff) {
#ifdef BASOP_NOGLOB
        set_flag (Overflow);
        set_overflow (Overflow);
        L40_var_out = MAX_40;
#else /* BASOP_NOGLOB */
        L40_var_out = L40_OVERFLOW_OCCURED (L40_var_out);
@@ -161,7 +161,7 @@ Word40 L40_shl (Word40 L40_var1, Word16 var2) {

      else if (L40_var_out < L40_constant) {
#ifdef BASOP_NOGLOB
        set_flag (Overflow);
        set_overflow (Overflow);
        L40_var_out = MIN_40;
#else /* BASOP_NOGLOB */
        L40_var_out = L40_UNDERFLOW_OCCURED (L40_var_out);
@@ -331,7 +331,7 @@ Word40 L40_add (Word40 L40_var1, Word40 L40_var2) {
      && (((L40_var2 & 0x8000000000) >> 39) != 0)
      && (((L40_var_out & 0x8000000000) >> 39) == 0)) {
#ifdef BASOP_NOGLOB
    set_flag (Overflow);
    set_overflow (Overflow);
    L40_var_out = MIN_40;
#else /* BASOP_NOGLOB */
    L40_var_out = L40_UNDERFLOW_OCCURED (L40_var_out);
@@ -341,7 +341,7 @@ Word40 L40_add (Word40 L40_var1, Word40 L40_var2) {
             && (((L40_var2 & 0x8000000000) >> 39) == 0)
             && (((L40_var_out & 0x8000000000) >> 39) != 0)) {
#ifdef BASOP_NOGLOB
    set_flag (Overflow);
    set_overflow (Overflow);
    L40_var_out = MAX_40;
#else /* BASOP_NOGLOB */
    L40_var_out = L40_OVERFLOW_OCCURED (L40_var_out);
@@ -404,7 +404,7 @@ Word40 L40_sub (Word40 L40_var1, Word40 L40_var2) {
      && (((L40_var2 & 0x8000000000) >> 39) == 0)
      && (((L40_var_out & 0x8000000000) >> 39) == 0)) {
#ifdef BASOP_NOGLOB
    set_flag (Overflow);
    set_overflow (Overflow);
    L40_var_out = MIN_40;
#else /* BASOP_NOGLOB */
    L40_var_out = L40_UNDERFLOW_OCCURED (L40_var_out);
@@ -414,7 +414,7 @@ Word40 L40_sub (Word40 L40_var1, Word40 L40_var2) {
             && (((L40_var2 & 0x8000000000) >> 39) != 0)
             && (((L40_var_out & 0x8000000000) >> 39) != 0)) {
#ifdef BASOP_NOGLOB
    set_flag (Overflow);
    set_overflow (Overflow);
    L40_var_out = MAX_40;
#else /* BASOP_NOGLOB */
    L40_var_out = L40_OVERFLOW_OCCURED (L40_var_out);
@@ -613,7 +613,7 @@ Word32 L_saturate40 (Word40 L40_var1) {
  if (L40_var1 < UNDER_L40_var2) {
    L40_var1 = UNDER_L40_var2;
#ifdef BASOP_NOGLOB
    set_flag (Overflow);
    set_overflow (Overflow);
#else /* BASOP_NOGLOB */
    Overflow = 1;
#endif /* BASOP_NOGLOB */
@@ -622,7 +622,7 @@ Word32 L_saturate40 (Word40 L40_var1) {
  if (L40_var1 > OVER_L40_var2) {
    L40_var1 = OVER_L40_var2;
#ifdef BASOP_NOGLOB
    set_flag (Overflow);
    set_overflow (Overflow);
#else /* BASOP_NOGLOB */
    Overflow = 1;
#endif /* BASOP_NOGLOB */
+9 −9
Original line number Diff line number Diff line
@@ -181,7 +181,7 @@ Word64 W_shl (Word64 L64_var1, Word16 var2) {
    for (; var2 > 0; var2--) { 
      if (L64_var1 > (Word64) 0X3fffffffffffffffLL) { 
#ifdef BASOP_NOGLOB
        set_flag(Overflow);
        set_overflow(Overflow);
#else /* BASOP_NOGLOB */
        Overflow = 1; 
#endif /* BASOP_NOGLOB */
@@ -191,7 +191,7 @@ Word64 W_shl (Word64 L64_var1, Word16 var2) {
      else { 
        if (L64_var1 < (Word64) 0xc000000000000000LL) { 
#ifdef BASOP_NOGLOB
          set_flag(Overflow);
          set_overflow(Overflow);
#else /* BASOP_NOGLOB */
          Overflow = 1; 
#endif /* BASOP_NOGLOB */
@@ -1126,7 +1126,7 @@ Word32 W_round48_L (Word64 L64_var1) {
    if ( (L64_var_out ^ L64_var1) & L64_MIN) { 
      L64_var_out = (L64_var1 < 0) ? L64_MIN : L64_MAX; 
#ifdef BASOP_NOGLOB
      set_flag(Overflow);
      set_overflow(Overflow);
#else /* BASOP_NOGLOB */
      Overflow = 1; 
#endif /* BASOP_NOGLOB */
@@ -1196,7 +1196,7 @@ Word16 W_round32_s (Word64 L64_var1) {
    if ((L64_var_out ^ L64_var1) & L64_MIN) { 
      L64_var_out = (L64_var1 < 0) ? L64_MIN : L64_MAX; 
#ifdef BASOP_NOGLOB
      set_flag(Overflow);
      set_overflow(Overflow);
#else /* BASOP_NOGLOB */
      Overflow = 1; 
#endif /* BASOP_NOGLOB */
@@ -1318,7 +1318,7 @@ Word64 W_add (Word64 L64_var1, Word64 L64_var2) {
        if ((L64_var_out ^ L64_var1) & MIN_64) {
            L64_var_out = (L64_var1 < 0) ? MIN_64 : MAX_64;
#ifdef BASOP_NOGLOB
            set_flag(Overflow);
            set_overflow(Overflow);
#else /* BASOP_NOGLOB */
            Overflow = 1;
#endif /* BASOP_NOGLOB */
@@ -1381,7 +1381,7 @@ Word64 W_sub (Word64 L64_var1, Word64 L64_var2) {
        if ((L64_var_out ^ L64_var1) & MIN_64) {
            L64_var_out = (L64_var1 < 0) ? MIN_64 : MAX_64;
#ifdef BASOP_NOGLOB
            set_flag(Overflow);
            set_overflow(Overflow);
#else /* BASOP_NOGLOB */
            Overflow = 1;
#endif /* BASOP_NOGLOB */
@@ -1438,7 +1438,7 @@ Word64 W_neg (Word64 L64_var1) {
  if (L64_var1 == MIN_64) { 
    L64_var_out = MAX_64;
#ifdef BASOP_NOGLOB
        set_flag(Overflow);
        set_overflow(Overflow);
#else /* BASOP_NOGLOB */
        Overflow = 1; 
#endif /* BASOP_NOGLOB */
@@ -1499,7 +1499,7 @@ Word64 W_abs (Word64 L64_var1) {
    if (L64_var1 == MIN_64) {
        L64_var_out = MAX_64; 
#ifdef BASOP_NOGLOB
    set_flag(Overflow);
    set_overflow(Overflow);
#else /* BASOP_NOGLOB */
    Overflow = 1;
#endif /* BASOP_NOGLOB */
@@ -1568,7 +1568,7 @@ Word64 W_mult_32_32(Word32 L_var1, Word32 L_var2) {
  if ((L_var1 == MIN_32) && (L_var2 == MIN_32)) { 
    L64_var_out = MAX_64; 
#ifdef BASOP_NOGLOB
    set_flag(Overflow);
    set_overflow(Overflow);
#else /* BASOP_NOGLOB */
    Overflow = 1; 
#endif /* BASOP_NOGLOB */
+3 −0
Original line number Diff line number Diff line
@@ -31,6 +31,9 @@
#define ENH_32_BIT_OPERATOR
#define BASOP_NOGLOB

// #define BASOP_NOGLOB_DEV_PRINT /* If enabled, warnings will be printed to stdout when an overflow occurs */
// #define BASOP_NOGLOB_DEV_ABORT /* If enabled, the program will abort when an overflow occurs */

#include "patch.h"
/* both ALLOW_40bits and ALLOW_ENH_UL32 shall be enabled for the EVS codec.  */
#define ALLOW_40bits         /* allow 32x16 and 32x32 multiplications */