+ switch (get_mode_sort(dst_mode)) {
+ case irms_float_number:
+ switch (get_mode_size_bits(dst_mode)) {
+ case 32:
+ fc_cast(src->value, 8, 23, NULL);
+ break;
+ case 64:
+ fc_cast(src->value, 11, 52, NULL);
+ break;
+ case 80:
+ fc_cast(src->value, 15, 64, NULL);
+ break;
+ default:
+ break;
+ }
+ 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:
+ assert(0);
+ break;
+ }
+ if (! fc_flt2int(res, sc_get_buffer(), dst_mode))
+ return tarval_bad;
+ return get_tarval(sc_get_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';
+ switch (get_mode_size_bits(dst_mode)) {
+ case 32:
+ fc_val_from_str(buffer, 0, 8, 23, NULL);
+ break;
+ case 64:
+ fc_val_from_str(buffer, 0, 11, 52, NULL);
+ break;
+ case 80:
+ fc_val_from_str(buffer, 0, 15, 64, NULL);
+ break;
+ }
+ 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);