#include #include #include inline void throw_overflow () { throw std::runtime_error( "Overflow!!!" ); } #define E void (*err)() //template inline int add( int op1, int op2, E ) { asm ( "add %1, %0" : "=r"(op1) : "r"(op2),"0"(op1) ); asm goto( "jo %l[throw_exception]" : : : "memory" : throw_exception ); return op1; throw_exception: err(); } //template inline long add( long op1, long op2, E) { asm ( "add %1, %0" : "=r"(op1) : "r"(op2),"0"(op1) ); asm goto( "jo %l[throw_exception]" : : : "memory" : throw_exception ); return op1; throw_exception: err(); } // Just test a possible implementation for 386 //template inline long long add( long long op1, long long op2, E ) { unsigned int op1l = (unsigned int)op1; unsigned int op1h = (unsigned int)((unsigned long long)op1 >> 32); unsigned int op2l = (unsigned int)op2; unsigned int op2h = (unsigned int)((unsigned long long)op2 >> 32); asm ( "add %2, %0\n" "adc %3, %1" : "=a"(op1l),"=d"(op1h) : "g"(op2l),"g"(op2h),"0"(op1l),"1"(op1h) ); asm goto( "jo %l[throw_exception]" : : : "memory" : throw_exception ); return (long long)((unsigned long long)op1l | ((unsigned long long)op1h << 32)); throw_exception: err(); } #if 0 // //GCC 4.5.2 crashes on this template. //I filed a bug against GCC. #55528 // template inline C add2( C op1, C op2 ) { asm ( "add %1, %0" : "=r"(op1) : "r"(op2),"0"(op1) ); asm goto( "jo %l[throw_exception]" : : : "memory" : throw_exception ); return op1; throw_exception: return throw_overflow(); } #endif template inline void test_add( C op1, C op2 ) {try { std::cout << op1 << " + " << op2 << " = "; std::cout.flush(); C r = add( op1, op2, &throw_overflow ); std::cout << r << std::endl; } catch ( const std::exception& e ) { std::cout << e.what() << std::endl; } catch ( ... ) { std::cout << "unknown exception" << std::endl; } } int main( void ) { test_add( 10, 20); test_add( 100, 200); test_add( 1000, 2000); test_add( 1000000000, 2000000000); test_add( 1000000000, -2000000000); test_add( -1000000000, 2000000000); test_add( -1000000000, -2000000000); test_add( 1000000000L, 2000000000L); test_add( 1000000000L,-2000000000L); test_add( -1000000000L, 2000000000L); test_add( -1000000000L,-2000000000L); test_add( 7000000000000000000L, 8000000000000000000L); test_add( 7000000000000000000L, -8000000000000000000L); test_add( -7000000000000000000L, 8000000000000000000L); test_add( -7000000000000000000L, -8000000000000000000L); test_add( (long long)7000000000000000000L, (long long)8000000000000000000L); test_add( (long long)7000000000000000000L, (long long)-8000000000000000000L); test_add( (long long)-7000000000000000000L, (long long)8000000000000000000L); test_add( (long long)-7000000000000000000L, (long long)-8000000000000000000L); return 0; }