static struct value * scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) { struct value *val; struct type *type1, *type2, *result_type; arg1 = coerce_ref (arg1); arg2 = coerce_ref (arg2); type1 = check_typedef (value_type (arg1)); type2 = check_typedef (value_type (arg2)); if ((TYPE_CODE (type1) != TYPE_CODE_FLT && TYPE_CODE (type1) != TYPE_CODE_DECFLOAT && !is_integral_type (type1)) || (TYPE_CODE (type2) != TYPE_CODE_FLT && TYPE_CODE (type2) != TYPE_CODE_DECFLOAT && !is_integral_type (type2))) error (_("Argument to arithmetic operation not a number or boolean.")); if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT || TYPE_CODE (type2) == TYPE_CODE_DECFLOAT) { int len_v1, len_v2, len_v; enum bfd_endian byte_order_v1, byte_order_v2, byte_order_v; gdb_byte v1[16], v2[16]; gdb_byte v[16]; /* If only one type is decimal float, use its type. Otherwise use the bigger type. */ if (TYPE_CODE (type1) != TYPE_CODE_DECFLOAT) result_type = type2; else if (TYPE_CODE (type2) != TYPE_CODE_DECFLOAT) result_type = type1; else if (TYPE_LENGTH (type2) > TYPE_LENGTH (type1)) result_type = type2; else result_type = type1; len_v = TYPE_LENGTH (result_type); byte_order_v = gdbarch_byte_order (get_type_arch (result_type)); value_args_as_decimal (arg1, arg2, v1, &len_v1, &byte_order_v1, v2, &len_v2, &byte_order_v2); switch (op) { case BINOP_ADD: case BINOP_SUB: case BINOP_MUL: case BINOP_DIV: case BINOP_EXP: decimal_binop (op, v1, len_v1, byte_order_v1, v2, len_v2, byte_order_v2, v, len_v, byte_order_v); break; default: error (_("Operation not valid for decimal floating point number.")); } val = value_from_decfloat (result_type, v); } else if (TYPE_CODE (type1) == TYPE_CODE_FLT || TYPE_CODE (type2) == TYPE_CODE_FLT) { /* FIXME-if-picky-about-floating-accuracy: Should be doing this in target format. real.c in GCC probably has the necessary code. */ DOUBLEST v1, v2, v = 0; v1 = value_as_double (arg1); v2 = value_as_double (arg2); switch (op) { case BINOP_ADD: v = v1 + v2; break; case BINOP_SUB: v = v1 - v2; break; case BINOP_MUL: v = v1 * v2; break; case BINOP_DIV: v = v1 / v2; break; case BINOP_EXP: errno = 0; v = pow (v1, v2); if (errno) error (_("Cannot perform exponentiation: %s"), safe_strerror (errno)); break; case BINOP_MIN: v = v1 < v2 ? v1 : v2; break; case BINOP_MAX: v = v1 > v2 ? v1 : v2; break; default: error (_("Integer-only operation on floating point number.")); } /* If only one type is float, use its type. Otherwise use the bigger type. */ if (TYPE_CODE (type1) != TYPE_CODE_FLT) result_type = type2; else if (TYPE_CODE (type2) != TYPE_CODE_FLT) result_type = type1; else if (TYPE_LENGTH (type2) > TYPE_LENGTH (type1)) result_type = type2; else result_type = type1; val = allocate_value (result_type); store_typed_floating (value_contents_raw (val), value_type (val), v); } else if (TYPE_CODE (type1) == TYPE_CODE_BOOL || TYPE_CODE (type2) == TYPE_CODE_BOOL) { LONGEST v1, v2, v = 0; v1 = value_as_long (arg1); v2 = value_as_long (arg2); switch (op) { case BINOP_BITWISE_AND: v = v1 & v2; break; case BINOP_BITWISE_IOR: v = v1 | v2; break; case BINOP_BITWISE_XOR: v = v1 ^ v2; break; case BINOP_EQUAL: v = v1 == v2; break; case BINOP_NOTEQUAL: v = v1 != v2; break; default: error (_("Invalid operation on booleans.")); } result_type = type1; val = allocate_value (result_type); store_signed_integer (value_contents_raw (val), TYPE_LENGTH (result_type), gdbarch_byte_order (get_type_arch (result_type)), v); } else /* Integral operations here. */ { /* Determine type length of the result, and if the operation should be done unsigned. For exponentiation and shift operators, use the length and type of the left operand. Otherwise, use the signedness of the operand with the greater length. If both operands are of equal length, use unsigned operation if one of the operands is unsigned. */ if (op == BINOP_RSH || op == BINOP_LSH || op == BINOP_EXP) result_type = type1; else if (TYPE_LENGTH (type1) > TYPE_LENGTH (type2)) result_type = type1; else if (TYPE_LENGTH (type2) > TYPE_LENGTH (type1)) result_type = type2; else if (TYPE_UNSIGNED (type1)) result_type = type1; else if (TYPE_UNSIGNED (type2)) result_type = type2; else result_type = type1; if (TYPE_UNSIGNED (result_type)) { LONGEST v2_signed = value_as_long (arg2); ULONGEST v1, v2, v = 0; v1 = (ULONGEST) value_as_long (arg1); v2 = (ULONGEST) v2_signed; switch (op) { case BINOP_ADD: v = v1 + v2; break; case BINOP_SUB: v = v1 - v2; break; case BINOP_MUL: v = v1 * v2; break; case BINOP_DIV: case BINOP_INTDIV: if (v2 != 0) v = v1 / v2; else error (_("Division by zero")); break; case BINOP_EXP: v = uinteger_pow (v1, v2_signed); break; case BINOP_REM: if (v2 != 0) v = v1 % v2; else error (_("Division by zero")); break; case BINOP_MOD: /* Knuth 1.2.4, integer only. Note that unlike the C '%' op, v1 mod 0 has a defined value, v1. */ if (v2 == 0) { v = v1; } else { v = v1 / v2; /* Note floor(v1/v2) == v1/v2 for unsigned. */ v = v1 - (v2 * v); } break; case BINOP_LSH: v = v1 << v2; break; case BINOP_RSH: v = v1 >> v2; break; case BINOP_BITWISE_AND: v = v1 & v2; break; case BINOP_BITWISE_IOR: v = v1 | v2; break; case BINOP_BITWISE_XOR: v = v1 ^ v2; break; case BINOP_LOGICAL_AND: v = v1 && v2; break; case BINOP_LOGICAL_OR: v = v1 || v2; break; case BINOP_MIN: v = v1 < v2 ? v1 : v2; break; case BINOP_MAX: v = v1 > v2 ? v1 : v2; break; case BINOP_EQUAL: v = v1 == v2; break; case BINOP_NOTEQUAL: v = v1 != v2; break; case BINOP_LESS: v = v1 < v2; break; case BINOP_GTR: v = v1 > v2; break; case BINOP_LEQ: v = v1 <= v2; break; case BINOP_GEQ: v = v1 >= v2; break; default: error (_("Invalid binary operation on numbers.")); } val = allocate_value (result_type); store_unsigned_integer (value_contents_raw (val), TYPE_LENGTH (value_type (val)), gdbarch_byte_order (get_type_arch (result_type)), v); } else { LONGEST v1, v2, v = 0; v1 = value_as_long (arg1); v2 = value_as_long (arg2); switch (op) { case BINOP_ADD: v = v1 + v2; break; case BINOP_SUB: v = v1 - v2; break; case BINOP_MUL: v = v1 * v2; break; case BINOP_DIV: case BINOP_INTDIV: if (v2 != 0) v = v1 / v2; else error (_("Division by zero")); break; case BINOP_EXP: v = integer_pow (v1, v2); break; case BINOP_REM: if (v2 != 0) v = v1 % v2; else error (_("Division by zero")); break; case BINOP_MOD: /* Knuth 1.2.4, integer only. Note that unlike the C '%' op, X mod 0 has a defined value, X. */ if (v2 == 0) { v = v1; } else { v = v1 / v2; /* Compute floor. */ if (TRUNCATION_TOWARDS_ZERO && (v < 0) && ((v1 % v2) != 0)) { v--; } v = v1 - (v2 * v); } break; case BINOP_LSH: v = v1 << v2; break; case BINOP_RSH: v = v1 >> v2; break; case BINOP_BITWISE_AND: v = v1 & v2; break; case BINOP_BITWISE_IOR: v = v1 | v2; break; case BINOP_BITWISE_XOR: v = v1 ^ v2; break; case BINOP_LOGICAL_AND: v = v1 && v2; break; case BINOP_LOGICAL_OR: v = v1 || v2; break; case BINOP_MIN: v = v1 < v2 ? v1 : v2; break; case BINOP_MAX: v = v1 > v2 ? v1 : v2; break; case BINOP_EQUAL: v = v1 == v2; break; case BINOP_NOTEQUAL: v = v1 != v2; break; case BINOP_LESS: v = v1 < v2; break; case BINOP_GTR: v = v1 > v2; break; case BINOP_LEQ: v = v1 <= v2; break; case BINOP_GEQ: v = v1 >= v2; break; default: error (_("Invalid binary operation on numbers.")); } val = allocate_value (result_type); store_signed_integer (value_contents_raw (val), TYPE_LENGTH (value_type (val)), gdbarch_byte_order (get_type_arch (result_type)), v); } }
static struct value * scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) { struct value *val; struct type *type1, *type2, *result_type; arg1 = coerce_ref (arg1); arg2 = coerce_ref (arg2); type1 = check_typedef (value_type (arg1)); type2 = check_typedef (value_type (arg2)); if ((!is_floating_value (arg1) && !is_integral_type (type1)) || (!is_floating_value (arg2) && !is_integral_type (type2))) error (_("Argument to arithmetic operation not a number or boolean.")); if (is_floating_type (type1) || is_floating_type (type2)) { /* If only one type is floating-point, use its type. Otherwise use the bigger type. */ if (!is_floating_type (type1)) result_type = type2; else if (!is_floating_type (type2)) result_type = type1; else if (TYPE_LENGTH (type2) > TYPE_LENGTH (type1)) result_type = type2; else result_type = type1; val = allocate_value (result_type); struct type *eff_type_v1, *eff_type_v2; gdb::byte_vector v1, v2; v1.resize (TYPE_LENGTH (result_type)); v2.resize (TYPE_LENGTH (result_type)); value_args_as_target_float (arg1, arg2, v1.data (), &eff_type_v1, v2.data (), &eff_type_v2); target_float_binop (op, v1.data (), eff_type_v1, v2.data (), eff_type_v2, value_contents_raw (val), result_type); } else if (TYPE_CODE (type1) == TYPE_CODE_BOOL || TYPE_CODE (type2) == TYPE_CODE_BOOL) { LONGEST v1, v2, v = 0; v1 = value_as_long (arg1); v2 = value_as_long (arg2); switch (op) { case BINOP_BITWISE_AND: v = v1 & v2; break; case BINOP_BITWISE_IOR: v = v1 | v2; break; case BINOP_BITWISE_XOR: v = v1 ^ v2; break; case BINOP_EQUAL: v = v1 == v2; break; case BINOP_NOTEQUAL: v = v1 != v2; break; default: error (_("Invalid operation on booleans.")); } result_type = type1; val = allocate_value (result_type); store_signed_integer (value_contents_raw (val), TYPE_LENGTH (result_type), gdbarch_byte_order (get_type_arch (result_type)), v); } else /* Integral operations here. */ { /* Determine type length of the result, and if the operation should be done unsigned. For exponentiation and shift operators, use the length and type of the left operand. Otherwise, use the signedness of the operand with the greater length. If both operands are of equal length, use unsigned operation if one of the operands is unsigned. */ if (op == BINOP_RSH || op == BINOP_LSH || op == BINOP_EXP) result_type = type1; else if (TYPE_LENGTH (type1) > TYPE_LENGTH (type2)) result_type = type1; else if (TYPE_LENGTH (type2) > TYPE_LENGTH (type1)) result_type = type2; else if (TYPE_UNSIGNED (type1)) result_type = type1; else if (TYPE_UNSIGNED (type2)) result_type = type2; else result_type = type1; if (TYPE_UNSIGNED (result_type)) { LONGEST v2_signed = value_as_long (arg2); ULONGEST v1, v2, v = 0; v1 = (ULONGEST) value_as_long (arg1); v2 = (ULONGEST) v2_signed; switch (op) { case BINOP_ADD: v = v1 + v2; break; case BINOP_SUB: v = v1 - v2; break; case BINOP_MUL: v = v1 * v2; break; case BINOP_DIV: case BINOP_INTDIV: if (v2 != 0) v = v1 / v2; else error (_("Division by zero")); break; case BINOP_EXP: v = uinteger_pow (v1, v2_signed); break; case BINOP_REM: if (v2 != 0) v = v1 % v2; else error (_("Division by zero")); break; case BINOP_MOD: /* Knuth 1.2.4, integer only. Note that unlike the C '%' op, v1 mod 0 has a defined value, v1. */ if (v2 == 0) { v = v1; } else { v = v1 / v2; /* Note floor(v1/v2) == v1/v2 for unsigned. */ v = v1 - (v2 * v); } break; case BINOP_LSH: v = v1 << v2; break; case BINOP_RSH: v = v1 >> v2; break; case BINOP_BITWISE_AND: v = v1 & v2; break; case BINOP_BITWISE_IOR: v = v1 | v2; break; case BINOP_BITWISE_XOR: v = v1 ^ v2; break; case BINOP_LOGICAL_AND: v = v1 && v2; break; case BINOP_LOGICAL_OR: v = v1 || v2; break; case BINOP_MIN: v = v1 < v2 ? v1 : v2; break; case BINOP_MAX: v = v1 > v2 ? v1 : v2; break; case BINOP_EQUAL: v = v1 == v2; break; case BINOP_NOTEQUAL: v = v1 != v2; break; case BINOP_LESS: v = v1 < v2; break; case BINOP_GTR: v = v1 > v2; break; case BINOP_LEQ: v = v1 <= v2; break; case BINOP_GEQ: v = v1 >= v2; break; default: error (_("Invalid binary operation on numbers.")); } val = allocate_value (result_type); store_unsigned_integer (value_contents_raw (val), TYPE_LENGTH (value_type (val)), gdbarch_byte_order (get_type_arch (result_type)), v); } else { LONGEST v1, v2, v = 0; v1 = value_as_long (arg1); v2 = value_as_long (arg2); switch (op) { case BINOP_ADD: v = v1 + v2; break; case BINOP_SUB: v = v1 - v2; break; case BINOP_MUL: v = v1 * v2; break; case BINOP_DIV: case BINOP_INTDIV: if (v2 != 0) v = v1 / v2; else error (_("Division by zero")); break; case BINOP_EXP: v = integer_pow (v1, v2); break; case BINOP_REM: if (v2 != 0) v = v1 % v2; else error (_("Division by zero")); break; case BINOP_MOD: /* Knuth 1.2.4, integer only. Note that unlike the C '%' op, X mod 0 has a defined value, X. */ if (v2 == 0) { v = v1; } else { v = v1 / v2; /* Compute floor. */ if (TRUNCATION_TOWARDS_ZERO && (v < 0) && ((v1 % v2) != 0)) { v--; } v = v1 - (v2 * v); } break; case BINOP_LSH: v = v1 << v2; break; case BINOP_RSH: v = v1 >> v2; break; case BINOP_BITWISE_AND: v = v1 & v2; break; case BINOP_BITWISE_IOR: v = v1 | v2; break; case BINOP_BITWISE_XOR: v = v1 ^ v2; break; case BINOP_LOGICAL_AND: v = v1 && v2; break; case BINOP_LOGICAL_OR: v = v1 || v2; break; case BINOP_MIN: v = v1 < v2 ? v1 : v2; break; case BINOP_MAX: v = v1 > v2 ? v1 : v2; break; case BINOP_EQUAL: v = v1 == v2; break; case BINOP_NOTEQUAL: v = v1 != v2; break; case BINOP_LESS: v = v1 < v2; break; case BINOP_GTR: v = v1 > v2; break; case BINOP_LEQ: v = v1 <= v2; break; case BINOP_GEQ: v = v1 >= v2; break; default: error (_("Invalid binary operation on numbers.")); } val = allocate_value (result_type); store_signed_integer (value_contents_raw (val), TYPE_LENGTH (value_type (val)), gdbarch_byte_order (get_type_arch (result_type)), v); } }