+int
+smaller_mode(const ir_mode *sm, const ir_mode *lm)
+{
+ ANNOUNCE();
+ assert(sm);
+ assert(lm);
+
+ if (sm == lm) return 1;
+
+ switch(get_mode_sort(sm))
+ {
+ case irms_int_number:
+ switch(get_mode_sort(lm))
+ {
+ case irms_int_number:
+ /* integers are convertable if
+ * - both have the same sign and lm is the larger one
+ * - lm is the signed one and is at least two bits larger
+ * (one for the sign, one for the highest bit of sm)
+ */
+ if (mode_is_signed(sm))
+ {
+ if ( mode_is_signed(lm) && (get_mode_size_bits(lm) > get_mode_size_bits(sm)) )
+ return 1;
+ }
+ else if (mode_is_signed(lm))
+ {
+ if (get_mode_size_bits(lm) > get_mode_size_bits(sm) + 1)
+ return 1;
+ }
+ else if (get_mode_size_bits(lm) > get_mode_size_bits(sm))
+ {
+ return 1;
+ }
+ break;
+
+ case irms_float_number:
+ /* int to float works if the float is large enough */
+ return 0;
+
+ default:
+ break;
+ }
+ break;
+
+ case irms_float_number:
+ /* XXX currently only the three standard 32,64,80 bit floats
+ * are supported which can safely be converted */
+ if ( (get_mode_sort(lm) == irms_float_number)
+ && (get_mode_size_bits(lm) > get_mode_size_bits(sm)) )
+ return 1;
+ break;
+
+ case irms_reference:
+ /* do exist machines out there with different pointer lenghts ?*/
+ return 0;
+
+ default:
+ break;
+ }
+
+ /* else */
+ return 0;
+}
+
+/* ** initialization ** */
+void
+init_mode (void)
+{
+ ir_mode newmode;
+ ANNOUNCE();
+ /* init flexible array */
+
+ obstack_init(&modes);
+
+ num_modes = 0;
+ /* initialize predefined modes */
+
+ /* Internal Modes */
+ newmode.arithmetic = irma_none;
+ newmode.size = 0;
+ newmode.align = 0;
+ newmode.sign = 0;
+ newmode.link = NULL;
+ newmode.tv_priv = NULL;
+
+ /* Control Flow Modes*/
+ newmode.sort = irms_control_flow;
+
+ /* Basic Block */
+ newmode.name = id_from_str("BB", 2);
+ newmode.code = irm_BB;
+
+ mode_BB = register_mode(&newmode);
+
+/* eXecution */
+ newmode.name = id_from_str("X", 1);
+ newmode.code = irm_X;
+
+ mode_X = register_mode(&newmode);
+
+ /* Memory Modes */
+ newmode.sort = irms_memory;
+
+ /* Memory */
+ newmode.name = id_from_str("M", 1);
+ newmode.code = irm_M;
+
+ mode_M = register_mode(&newmode);
+
+ /* Auxiliary Modes */
+ newmode.sort = irms_auxiliary,
+
+ /* Tuple */
+ newmode.name = id_from_str("T", 1);
+ newmode.code = irm_T;
+
+ mode_T = register_mode(&newmode);
+
+ /* ANY */
+ newmode.name = id_from_str("ANY", 3);
+ newmode.code = irm_ANY;
+
+ mode_ANY = register_mode(&newmode);
+
+ /* BAD */
+ newmode.name = id_from_str("BAD", 3);
+ newmode.code = irm_BAD;
+
+ mode_BAD = register_mode(&newmode);
+
+ /* Internal Boolean Modes */
+ newmode.sort = irms_internal_boolean;
+
+ /* boolean */
+ newmode.name = id_from_str("b", 1);
+ newmode.code = irm_b;
+
+ mode_b = register_mode(&newmode);
+
+/* Data Modes */
+
+ /* Float Number Modes */
+ newmode.sort = irms_float_number;
+ newmode.arithmetic = irma_ieee754;
+
+ /* float */
+ newmode.name = id_from_str("F", 1);
+ newmode.code = irm_F;
+ newmode.sign = 1;
+ newmode.align = 4;
+ newmode.size = 32;
+
+ mode_F = register_mode(&newmode);
+
+ /* double */
+ newmode.name = id_from_str("D", 1);
+ newmode.code = irm_D;
+ newmode.sign = 1;
+ newmode.align = 4;
+ newmode.size = 64;
+
+ mode_D = register_mode(&newmode);
+
+ /* extended */
+ newmode.name = id_from_str("E", 1);
+ newmode.code = irm_E;
+ newmode.sign = 1;
+ newmode.align = 4;
+ newmode.size = 80;
+
+ mode_E = register_mode(&newmode);
+
+ /* Integer Number Modes */
+ newmode.sort = irms_int_number;
+ newmode.arithmetic = irma_twos_complement;
+
+ /* signed byte */
+ newmode.name = id_from_str("Bs", 2);
+ newmode.code = irm_Bs;
+ newmode.sign = 1;
+ newmode.align = 1;
+ newmode.size = 8;
+
+ mode_Bs = register_mode(&newmode);
+
+ /* unsigned byte */
+ newmode.name = id_from_str("Bu", 2);
+ newmode.code = irm_Bu;
+ newmode.arithmetic = irma_twos_complement;
+ newmode.sign = 0;
+ newmode.align = 1;
+ newmode.size = 8;
+
+ mode_Bu = register_mode(&newmode);
+
+ /* signed short integer */
+ newmode.name = id_from_str("Hs", 2);
+ newmode.code = irm_Hs;
+ newmode.sign = 1;
+ newmode.align = 2;
+ newmode.size = 16;
+
+ mode_Hs = register_mode(&newmode);
+
+ /* unsigned short integer */
+ newmode.name = id_from_str("Hu", 2);
+ newmode.code = irm_Hu;
+ newmode.sign = 0;
+ newmode.align = 2;
+ newmode.size = 16;
+
+ mode_Hu = register_mode(&newmode);
+
+ /* signed integer */
+ newmode.name = id_from_str("Is", 2);
+ newmode.code = irm_Is;
+ newmode.sign = 1;
+ newmode.align = 4;
+ newmode.size = 32;
+
+ mode_Is = register_mode(&newmode);
+
+ /* unsigned integer */
+ newmode.name = id_from_str("Iu", 2);
+ newmode.code = irm_Iu;
+ newmode.sign = 0;
+ newmode.align = 4;
+ newmode.size = 32;
+
+ mode_Iu = register_mode(&newmode);
+
+ /* signed long integer */
+ newmode.name = id_from_str("Ls", 2);
+ newmode.code = irm_Ls;
+ newmode.sign = 1;
+ newmode.align = 4;
+ newmode.size = 64;
+
+ mode_Ls = register_mode(&newmode);
+
+ /* unsigned long integer */
+ newmode.name = id_from_str("Lu", 2);
+ newmode.code = irm_Lu;
+ newmode.sign = 0;
+ newmode.align = 4;
+ newmode.size = 64;
+
+ mode_Lu = register_mode(&newmode);
+
+ /* Character Modes */
+ newmode.sort = irms_character;
+ newmode.arithmetic = irma_none;
+
+ /* Character */
+ newmode.name = id_from_str("C", 1);
+ newmode.code = irm_C;
+ newmode.sign = 0;
+ newmode.align = 1;
+ newmode.size = 8;
+
+ mode_C = register_mode(&newmode);
+
+ /* Unicode character */
+ newmode.name = id_from_str("U", 1);
+ newmode.code = irm_U;
+ newmode.sign = 0;
+ newmode.align = 2;
+ newmode.size = 16;
+
+ mode_U = register_mode(&newmode);
+
+ /* Reference Modes */
+ newmode.sort = irms_reference;
+ newmode.arithmetic = irma_twos_complement;
+
+ /* pointer */
+ newmode.name = id_from_str("P", 1);
+ newmode.code = irm_P;
+ newmode.sign = 0;
+ newmode.align = 4;
+ newmode.size = 32;
+
+ mode_P = register_mode(&newmode);
+
+ /* set the machine specific modes to the predifined ones */
+ mode_P_mach = mode_P;