-tarval *tarval_add(tarval *a, tarval *b) /* addition */
-{
- ANNOUNCE();
- assert(a);
- assert(b);
- assert((a->mode == b->mode) || (get_mode_sort(a->mode) == character && mode_is_int(b->mode)));
-
- switch (get_mode_sort(a->mode))
- {
- case character:
- case int_number:
- /* modes of a,b are equal, so result has mode of a as this might be the character */
- sc_add(a->value, b->value);
- /* FIXME: Check for overflow */
- return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
-
- case float_number:
- /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */
- fc_add(a->value, b->value);
- return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
-
- default:
- return tarval_bad;
- }
+/*
+ * convert to other mode
+ */
+tarval *tarval_convert_to(tarval *src, ir_mode *m) {
+ char *buffer;
+
+ 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/characters to something */
+ case irms_int_number:
+ case irms_character:
+ switch (get_mode_sort(m)) {
+ case irms_int_number:
+ case irms_character:
+ buffer = alloca(sc_get_buffer_length());
+ memcpy(buffer, src->value, sc_get_buffer_length());
+ sign_extend(buffer, m);
+ return get_tarval_overflow(buffer, 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, mode_is_signed(src->mode)));
+ buffer[100 - 1] = '\0';
+ 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);
+
+ case irms_reference:
+ /* allow 0 to be casted */
+ if (src == get_mode_null(src->mode))
+ return get_mode_null(m);
+ break;
+
+ 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_reference:
+ switch(get_mode_sort(m)) {
+ case 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, m);
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ return tarval_bad;