-tarval *tarval_convert_to(tarval *src, ir_mode *m)
-{
- char *buffer;
-
- ANNOUNCE();
- assert(src);
- assert(m);
-
- if (src->mode == m) return src;
-
- if (get_mode_n_vector_elems(src->mode) > 1) {
- /* vector arithmetic not implemented yet */
- return tarval_bad;
- }
-
- 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(m)) {
- case irms_float_number:
- switch (get_mode_size_bits(m))
- {
- 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(), m);
-
- case irms_int_number:
- switch (GET_FLOAT_TO_INT_MODE())
- {
- case TRUNCATE:
- fc_int(src->value, NULL);
- break;
- case ROUND:
- fc_rnd(src->value, NULL);
- break;
- default:
- assert(0);
- break;
- }
- /* FIXME: floating point unit can't produce a value in integer
- * representation
- * an intermediate representation is needed here first. */
- /* return get_tarval(); */
- return tarval_bad;
-
- default:
- /* the rest can't be converted */
- return tarval_bad;
- }
- break;
-
- /* cast int to something */
- case irms_int_number:
- switch (get_mode_sort(m)) {
- case irms_int_number:
- case irms_character:
- return get_tarval_overflow(src->value, src->length, m);
-
- 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));
- switch (get_mode_size_bits(m))
- {
- 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(), m);
-
-#if 0
- case irms_reference:
- /* allow 0 to be casted */
- if (src == get_mode_null(src->mode))
- return get_mode_null(m);
- break;
-#endif
- default:
- break;
- }
- break;
-
- case irms_internal_boolean:
- switch (get_mode_sort(m))
- {
- case irms_int_number:
- if (src == tarval_b_true) return get_mode_one(m);
- else return get_mode_null(m);
-
- default:
- break;
- }
- break;
-
- case irms_character:
- break;
- case irms_reference:
- break;
- }
-
- return tarval_bad;
+tarval *tarval_convert_to(tarval *src, ir_mode *dst_mode)
+{
+ char *buffer;
+ fp_value *res = NULL;
+ const ieee_descriptor_t *desc;
+ int len;
+
+ carry_flag = -1;
+
+ assert(src);
+ assert(dst_mode);
+
+ if (src->mode == dst_mode)
+ return src;
+
+ if (get_mode_n_vector_elems(src->mode) > 1) {
+ /* vector arithmetic not implemented yet */
+ return tarval_bad;
+ }
+
+ 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 (current_float_to_int_mode) {
+ case TRUNCATE:
+ res = fc_int(src->value, NULL);
+ break;
+ case ROUND:
+ res = fc_rnd(src->value, NULL);
+ 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 */
+ len = 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, len, 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;