#include <assert.h> /* assertions */
#include <stdlib.h> /* atoi() */
-#include <string.h> /* nice things for strings */
+#ifdef HAVE_STRING_H
+# include <string.h> /* nice things for strings */
+#endif
#ifdef HAVE_STRINGS_H
#include <strings.h> /* strings.h also includes bsd only function strcasecmp */
#endif
#include "entity_t.h" /* needed to store pointers to entities */
#include "irmode_t.h"
#include "irnode.h" /* defines boolean return values (pnc_number)*/
-#include "host.h"
#include "strcalc.h"
#include "fltcalc.h"
target values */
#define N_CONSTANTS 2048
-/* XXX hack until theres's a proper interface */
-#define BAD 1
-#define SATURATE 2
-#define WRAP 3
-#define GET_OVERFLOW_MODE() BAD
+/* get the integer overflow mode */
+#define GET_OVERFLOW_MODE() int_overflow_mode
/* unused, float to int doesn't work yet */
#define TRUNCATE 1
****************************************************************************/
static struct set *tarvals; /* container for tarval structs */
static struct set *values; /* container for values */
+static tarval_int_overflow_mode_t int_overflow_mode = TV_OVERFLOW_WRAP;
/****************************************************************************
* private functions
return (tarval *)INSERT_TARVAL(&tv);
}
+/**
+ * handle overflow
+ */
static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode)
{
switch (get_mode_sort(mode))
case irms_int_number:
if (sc_comp(value, get_mode_max(mode)->value) == 1) {
switch (GET_OVERFLOW_MODE()) {
- case SATURATE:
+ case TV_OVERFLOW_SATURATE:
return get_mode_max(mode);
- case WRAP:
+ case TV_OVERFLOW_WRAP:
{
char *temp = alloca(sc_get_buffer_length());
char *diff = alloca(sc_get_buffer_length());
sc_sub(temp, diff, temp);
return get_tarval(temp, length, mode);
}
- case BAD:
+ case TV_OVERFLOW_BAD:
return tarval_bad;
default:
return get_tarval(value, length, mode);
}
if (sc_comp(value, get_mode_min(mode)->value) == -1) {
switch (GET_OVERFLOW_MODE()) {
- case SATURATE:
+ case TV_OVERFLOW_SATURATE:
return get_mode_min(mode);
- case WRAP:
+ case TV_OVERFLOW_WRAP:
{
char *temp = alloca(sc_get_buffer_length());
char *diff = alloca(sc_get_buffer_length());
sc_add(temp, diff, temp);
return get_tarval(temp, length, mode);
}
- case BAD:
+ case TV_OVERFLOW_BAD:
return tarval_bad;
default:
return get_tarval(value, length, mode);
/*
* Access routines for tarval fields ========================================
*/
-ir_mode *get_tarval_mode (tarval *tv) /* get the mode of the tarval */
-{
- ANNOUNCE();
- assert(tv);
- return tv->mode;
+
+/* get the mode of the tarval */
+ir_mode *(get_tarval_mode)(const tarval *tv) {
+ return _get_tarval_mode(tv);
}
/*
* therefore the irmode functions should be prefered to the functions below.
*/
-tarval *get_tarval_bad(void)
-{
- ANNOUNCE();
- return tarval_bad;
+tarval *(get_tarval_bad)(void) {
+ return _get_tarval_bad();
}
-tarval *get_tarval_undefined(void)
-{
- ANNOUNCE();
- return tarval_undefined;
+
+tarval *(get_tarval_undefined)(void) {
+ return _get_tarval_undefined();
}
-tarval *get_tarval_b_false(void)
-{
- ANNOUNCE();
- return tarval_b_false;
+
+tarval *(get_tarval_b_false)(void) {
+ return _get_tarval_b_false();
}
-tarval *get_tarval_b_true(void)
-{
- ANNOUNCE();
- return tarval_b_true;
+
+tarval *(get_tarval_b_true)(void) {
+ return _get_tarval_b_true();
}
-tarval *get_tarval_P_void(void)
-{
- ANNOUNCE();
- return tarval_P_void;
+
+tarval *(get_tarval_P_void)(void) {
+ return _get_tarval_P_void();
}
tarval *get_tarval_max(ir_mode *mode)
return tarval_bad;
}
+tarval *get_tarval_minus_one(ir_mode *mode)
+{
+ ANNOUNCE();
+ assert(mode);
+
+ if (get_mode_n_vector_elems(mode) > 1) {
+ /* vector arithmetic not implemented yet */
+ return tarval_bad;
+ }
+
+ switch(get_mode_sort(mode))
+ {
+ case irms_control_flow:
+ case irms_memory:
+ case irms_auxiliary:
+ case irms_internal_boolean:
+ case irms_reference:
+ assert(0);
+ break;
+
+ case irms_float_number:
+ return mode_is_signed(mode) ? new_tarval_from_double(-1.0, mode) : tarval_bad;
+
+ case irms_int_number:
+ case irms_character:
+ return mode_is_signed(mode) ? new_tarval_from_long(-1l, mode) : tarval_bad;
+ }
+ return tarval_bad;
+}
+
tarval *get_tarval_nan(ir_mode *mode)
{
ANNOUNCE();
}
}
-tarval *get_tarval_inf(ir_mode *mode)
+tarval *get_tarval_plus_inf(ir_mode *mode)
{
ANNOUNCE();
assert(mode);
}
}
+tarval *get_tarval_minus_inf(ir_mode *mode)
+{
+ ANNOUNCE();
+ assert(mode);
+
+ if (get_mode_n_vector_elems(mode) > 1) {
+ /* vector arithmetic not implemented yet */
+ return tarval_bad;
+ }
+
+ if (get_mode_sort(mode) == irms_float_number) {
+ switch(get_mode_size_bits(mode))
+ {
+ case 32:
+ fc_get_minusinf(8, 23, NULL);
+ break;
+ case 64:
+ fc_get_minusinf(11, 52, NULL);
+ break;
+ case 80:
+ fc_get_minusinf(15, 64, NULL);
+ break;
+ }
+ return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
+ }
+ else {
+ assert(0 && "tarval is not floating point");
+ return tarval_bad;
+ }
+}
+
/*
* Arithmethic operations on tarvals ========================================
*/
/*
* comparison
*/
-pnc_number tarval_cmp(tarval *a, tarval *b)
+pn_Cmp tarval_cmp(tarval *a, tarval *b)
{
ANNOUNCE();
assert(a);
assert(b);
- if (a == tarval_bad || b == tarval_bad) assert(0 && "Comparison with tarval_bad");
- if (a == tarval_undefined || b == tarval_undefined) return False;
- if (a == b) return Eq;
- if (a->mode != b->mode) return False;
+ if (a == tarval_bad || b == tarval_bad) {
+ assert(0 && "Comparison with tarval_bad");
+ return pn_Cmp_False;
+ }
+
+ if (a == tarval_undefined || b == tarval_undefined)
+ return pn_Cmp_False;
+
+ if (a->mode != b->mode)
+ return pn_Cmp_False;
if (get_mode_n_vector_elems(a->mode) > 1) {
/* vector arithmetic not implemented yet */
case irms_memory:
case irms_auxiliary:
case irms_reference:
- return False;
+ if (a == b)
+ return pn_Cmp_Eq;
+ return pn_Cmp_False;
case irms_float_number:
+ /*
+ * BEWARE: we cannot compare a == b here, because
+ * a NaN is always Unordered to any other value, even to itself!
+ */
switch (fc_comp(a->value, b->value)) {
- case -1: return Lt;
- case 0: assert(0 && "different tarvals compare equal"); return Eq;
- case 1: return Gt;
- case 2: return Uo;
- default: return False;
+ case -1: return pn_Cmp_Lt;
+ case 0: return pn_Cmp_Eq;
+ case 1: return pn_Cmp_Gt;
+ case 2: return pn_Cmp_Uo;
+ default: return pn_Cmp_False;
}
case irms_int_number:
case irms_character:
- return (sc_comp(a->value, b->value)==1)?(Gt):(Lt);
+ if (a == b)
+ return pn_Cmp_Eq;
+ return sc_comp(a->value, b->value) == 1 ? pn_Cmp_Gt : pn_Cmp_Lt;
case irms_internal_boolean:
- return (a == tarval_b_true)?(Gt):(Lt);
+ if (a == b)
+ return pn_Cmp_Eq;
+ return a == tarval_b_true ? pn_Cmp_Gt : pn_Cmp_Lt;
}
- return False;
+ return pn_Cmp_False;
}
/*
/* cast float to something */
case irms_float_number:
switch (get_mode_sort(m)) {
- case irms_float_number:
+ case irms_float_number:
switch (get_mode_size_bits(m))
{
case 32:
break;
}
return get_tarval(fc_get_buffer(), fc_get_buffer_length(), m);
- break;
case irms_int_number:
switch (GET_FLOAT_TO_INT_MODE())
* an intermediate representation is needed here first. */
/* return get_tarval(); */
return tarval_bad;
- break;
default:
/* the rest can't be converted */
ANNOUNCE();
assert(a);
assert(mode_is_num(a->mode)); /* negation only for numerical values */
- assert(mode_is_signed(a->mode)); /* negation is difficult without negative numbers, isn't it */
+
+ /* note: negation is allowed even for unsigned modes. */
if (get_mode_n_vector_elems(a->mode) > 1) {
/* vector arithmetic not implemented yet */
ANNOUNCE();
assert(a);
assert(b);
- assert((a->mode == b->mode) || (get_mode_sort(a->mode) == irms_character && mode_is_int(b->mode)));
+ assert(a->mode == b->mode);
if (get_mode_n_vector_elems(a->mode) > 1 || get_mode_n_vector_elems(b->mode) > 1) {
/* vector arithmetic not implemented yet */
ANNOUNCE();
assert(a);
assert(b);
- assert((a->mode == b->mode) || (get_mode_sort(a->mode) == irms_character && mode_is_int(b->mode)));
+ assert(a->mode == b->mode);
if (get_mode_n_vector_elems(a->mode) > 1 || get_mode_n_vector_elems(b->mode) > 1) {
/* vector arithmetic not implemented yet */
ANNOUNCE();
assert(a);
assert(b);
- assert((a->mode == b->mode) && mode_is_num(a->mode));
+ assert(a->mode == b->mode);
if (get_mode_n_vector_elems(a->mode) > 1) {
/* vector arithmetic not implemented yet */
return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
}
+/*
+ * carry flag of the last operation
+ */
+int tarval_carry(void)
+{
+ return sc_had_carry();
+}
/*
* Output of tarvals
case irms_reference:
if (tv == tarval_P_void) return snprintf(buf, len, "NULL");
if (tv->value != NULL){
- if (len > tv->length) {
- memcpy(buf, tv->value, tv->length);
- buf[tv->length] = '\0';
- }
- else {
- /* truncated */
- memcpy(buf, tv->value, len-1);
- buf[len-1] = '\0';
- }
- return tv->length;
+ if (len > tv->length) {
+ memcpy(buf, tv->value, tv->length);
+ buf[tv->length] = '\0';
+ }
+ else {
+ /* truncated */
+ memcpy(buf, tv->value, len-1);
+ buf[len-1] = '\0';
+ }
+ return tv->length;
}
else
- return snprintf(buf, len, "void");
+ return snprintf(buf, len, "void");
case irms_internal_boolean:
switch (mode_info->mode_output) {
case irms_control_flow:
case irms_memory:
case irms_auxiliary:
- return snprintf(buf, len, "<BAD>");
+ return snprintf(buf, len, "<TV_OVERFLOW_BAD>");
}
return 0;
byte = get_tarval_sub_bits(tv, i);
for(j = 1; j < 256; j <<= 1)
if(pos < n)
- res[pos++] = j & byte ? '1' : '0';
+ res[pos++] = j & byte ? '1' : '0';
}
res[n] = '\0';
/*
* Returns the output options of one mode.
*
- * This functions returns the modinfo of a given mode.
+ * This functions returns the mode info of a given mode.
*/
const tarval_mode_info *get_tarval_mode_output_option(ir_mode *mode)
{
return TV_CLASSIFY_OTHER;
}
+/**
+ * Sets the overflow mode for integer operations.
+ */
+void tarval_set_integer_overflow_mode(tarval_int_overflow_mode_t ov_mode) {
+ int_overflow_mode = ov_mode;
+}
+
+/**
+ * Get the overflow mode for integer operations.
+ */
+tarval_int_overflow_mode_t tarval_get_integer_overflow_mode(void) {
+ return int_overflow_mode;
+}
+
/**
* default mode_info for output as HEX
*/