+ switch (get_mode_sort(src->mode)) {
+ case irms_control_flow:
+ case irms_memory:
+ case irms_auxiliary:
+ break;
+
+ /* cast float to something */
+ case irms_float_number:
+ switch (get_mode_sort(dst_mode)) {
+ case irms_float_number:
+ desc = get_descriptor(dst_mode);
+ fc_cast(src->value, desc, NULL);
+ return get_tarval(fc_get_buffer(), fc_get_buffer_length(), dst_mode);
+
+ case irms_int_number:
+ switch (GET_FLOAT_TO_INT_MODE()) {
+ case TRUNCATE:
+ res = fc_int(src->value, NULL);
+ break;
+ case ROUND:
+ res = fc_rnd(src->value, NULL);
+ break;
+ default:
+ panic("Unsupported float to int conversion mode in tarval_convert_to()");
+ break;
+ }
+ buffer = alloca(sc_get_buffer_length());
+ if (! fc_flt2int(res, buffer, dst_mode))
+ return tarval_bad;
+ return get_tarval(buffer, sc_get_buffer_length(), dst_mode);
+
+ default:
+ /* the rest can't be converted */
+ return tarval_bad;
+ }
+ break;
+
+ /* cast int/characters to something */
+ case irms_int_number:
+ switch (get_mode_sort(dst_mode)) {
+
+ case irms_reference:
+ case irms_int_number:
+ buffer = alloca(sc_get_buffer_length());
+ memcpy(buffer, src->value, sc_get_buffer_length());
+ sign_extend(buffer, dst_mode);
+ return get_tarval_overflow(buffer, src->length, dst_mode);
+
+ case irms_internal_boolean:
+ /* XXX C semantics */
+ if (src == get_mode_null(src->mode)) return tarval_b_false;
+ else return tarval_b_true;
+
+ case irms_float_number:
+ /* XXX floating point unit does not understand internal integer
+ * representation, convert to string first, then create float from
+ * string */
+ buffer = alloca(100);
+ /* decimal string representation because hexadecimal output is
+ * interpreted unsigned by fc_val_from_str, so this is a HACK */
+ snprintf(buffer, 100, "%s",
+ sc_print(src->value, get_mode_size_bits(src->mode), SC_DEC, mode_is_signed(src->mode)));
+ buffer[100 - 1] = '\0';
+ desc = get_descriptor(dst_mode);
+ fc_val_from_str(buffer, 0, desc, NULL);
+ return get_tarval(fc_get_buffer(), fc_get_buffer_length(), dst_mode);
+
+ default:
+ break;
+ }
+ break;
+
+ case irms_internal_boolean:
+ /* beware: this is C semantic for the INTERNAL boolean mode */
+ if (get_mode_sort(dst_mode) == irms_int_number)
+ return src == tarval_b_true ? get_mode_one(dst_mode) : get_mode_null(dst_mode);
+ break;
+
+ case irms_reference:
+ if (get_mode_sort(dst_mode) == irms_int_number) {
+ buffer = alloca(sc_get_buffer_length());
+ memcpy(buffer, src->value, sc_get_buffer_length());
+ sign_extend(buffer, src->mode);
+ return get_tarval_overflow(buffer, src->length, dst_mode);
+ }
+ break;
+ }
+
+ return tarval_bad;
+}
+
+/*
+ * bitwise negation
+ */
+tarval *tarval_not(tarval *a) {
+ char *buffer;
+
+ assert(a);
+
+ /* works for vector mode without changes */
+
+ switch (get_mode_sort(a->mode)) {
+ case irms_reference:
+ case irms_int_number:
+ buffer = alloca(sc_get_buffer_length());
+ sc_not(a->value, buffer);
+ return get_tarval(buffer, a->length, a->mode);
+
+ case irms_internal_boolean:
+ if (a == tarval_b_true)
+ return tarval_b_false;
+ if (a == tarval_b_false)
+ return tarval_b_true;
+ return tarval_bad;
+
+ default:
+ assert(0 && "bitwise negation is only allowed for integer and boolean");
+ return tarval_bad;
+ }