some cleanups for middleend node creation in backends
[libfirm] / ir / be / sparc / sparc_emitter.c
index d0a8507..413b59a 100644 (file)
@@ -64,15 +64,6 @@ static const ir_node *delay_slot_filler; /**< this node has been choosen to fill
 
 static void sparc_emit_node(const ir_node *node);
 
-/**
- * Returns the register at in position pos.
- */
-static const arch_register_t *get_in_reg(const ir_node *node, int pos)
-{
-       ir_node *op = get_irn_n(node, pos);
-       return arch_get_irn_register(op);
-}
-
 void sparc_emit_immediate(const ir_node *node)
 {
        const sparc_attr_t *attr   = get_sparc_attr_const(node);
@@ -83,7 +74,11 @@ void sparc_emit_immediate(const ir_node *node)
                assert(sparc_is_value_imm_encodeable(value));
                be_emit_irprintf("%d", value);
        } else {
-               be_emit_cstring("%lo(");
+               if (get_entity_owner(entity) == get_tls_type()) {
+                       be_emit_cstring("%tle_lox10(");
+               } else {
+                       be_emit_cstring("%lo(");
+               }
                be_gas_emit_entity(entity);
                if (attr->immediate_value != 0) {
                        be_emit_irprintf("%+d", attr->immediate_value);
@@ -97,29 +92,33 @@ void sparc_emit_high_immediate(const ir_node *node)
        const sparc_attr_t *attr   = get_sparc_attr_const(node);
        ir_entity          *entity = attr->immediate_value_entity;
 
-       be_emit_cstring("%hi(");
        if (entity == NULL) {
                uint32_t value = (uint32_t) attr->immediate_value;
-               be_emit_irprintf("0x%X", value);
+               be_emit_irprintf("%%hi(0x%X)", value);
        } else {
+               if (get_entity_owner(entity) == get_tls_type()) {
+                       be_emit_cstring("%tle_hix22(");
+               } else {
+                       be_emit_cstring("%hi(");
+               }
                be_gas_emit_entity(entity);
                if (attr->immediate_value != 0) {
                        be_emit_irprintf("%+d", attr->immediate_value);
                }
+               be_emit_char(')');
        }
-       be_emit_char(')');
 }
 
 void sparc_emit_source_register(const ir_node *node, int pos)
 {
-       const arch_register_t *reg = get_in_reg(node, pos);
+       const arch_register_t *reg = arch_get_irn_register_in(node, pos);
        be_emit_char('%');
        be_emit_string(arch_register_get_name(reg));
 }
 
 void sparc_emit_dest_register(const ir_node *node, int pos)
 {
-       const arch_register_t *reg = arch_irn_get_register(node, pos);
+       const arch_register_t *reg = arch_get_irn_register_out(node, pos);
        be_emit_char('%');
        be_emit_string(arch_register_get_name(reg));
 }
@@ -131,7 +130,7 @@ void sparc_emit_dest_register(const ir_node *node, int pos)
  */
 void sparc_emit_reg_or_imm(const ir_node *node, int pos)
 {
-       if (arch_irn_get_flags(node) & ((arch_irn_flags_t)sparc_arch_irn_flag_immediate_form)) {
+       if (arch_get_irn_flags(node) & ((arch_irn_flags_t)sparc_arch_irn_flag_immediate_form)) {
                // we have a imm input
                sparc_emit_immediate(node);
        } else {
@@ -223,16 +222,6 @@ void sparc_emit_store_mode(const ir_node *node)
        }
 }
 
-/**
- * emit integer signed/unsigned prefix char
- */
-void sparc_emit_mode_sign_prefix(const ir_node *node)
-{
-       ir_mode *mode      = get_irn_mode(node);
-       bool     is_signed = mode_is_signed(mode);
-       be_emit_string(is_signed ? "s" : "u");
-}
-
 static void emit_fp_suffix(const ir_mode *mode)
 {
        unsigned bits = get_mode_size_bits(mode);
@@ -300,8 +289,8 @@ static bool is_no_instruction(const ir_node *node)
 {
        /* copies are nops if src_reg == dest_reg */
        if (be_is_Copy(node) || be_is_CopyKeep(node)) {
-               const arch_register_t *src_reg  = get_in_reg(node, 0);
-               const arch_register_t *dest_reg = arch_irn_get_register(node, 0);
+               const arch_register_t *src_reg  = arch_get_irn_register_in(node, 0);
+               const arch_register_t *dest_reg = arch_get_irn_register_out(node, 0);
 
                if (src_reg == dest_reg)
                        return true;
@@ -337,7 +326,12 @@ static bool emits_multiple_instructions(const ir_node *node)
        if (has_delay_slot(node))
                return true;
 
-       return is_sparc_Mulh(node) || is_sparc_SDiv(node) || is_sparc_UDiv(node)
+       if (is_sparc_Call(node)) {
+               return arch_get_irn_flags(node) & sparc_arch_irn_flag_aggregate_return;
+       }
+
+       return is_sparc_SMulh(node) || is_sparc_UMulh(node)
+               || is_sparc_SDiv(node) || is_sparc_UDiv(node)
                || be_is_MemPerm(node) || be_is_Perm(node);
 }
 
@@ -403,6 +397,11 @@ static const ir_node *pick_delay_slot_for(const ir_node *node)
                if (emits_multiple_instructions(schedpoint))
                        continue;
 
+               /* if check and schedpoint are not in the same block, give up. */
+               if (check != NULL
+                               && get_nodes_block(check) != get_nodes_block(schedpoint))
+                       break;
+
                /* allowed for delayslot: any instruction which is not necessary to
                 * compute an input to the branch. */
                if (check != NULL
@@ -447,7 +446,12 @@ static void emit_be_IncSP(const ir_node *irn)
 static void emit_sparc_Mulh(const ir_node *irn)
 {
        be_emit_cstring("\t");
-       sparc_emit_mode_sign_prefix(irn);
+       if (is_sparc_UMulh(irn)) {
+               be_emit_char('u');
+       } else {
+               assert(is_sparc_SMulh(irn));
+               be_emit_char('s');
+       }
        be_emit_cstring("mul ");
 
        sparc_emit_source_register(irn, 0);
@@ -531,6 +535,11 @@ static void emit_sparc_Call(const ir_node *node)
        be_emit_finish_line_gas(node);
 
        fill_delay_slot();
+
+       if (arch_get_irn_flags(node) & sparc_arch_irn_flag_aggregate_return) {
+               be_emit_cstring("\tunimp 8\n");
+               be_emit_write_line();
+       }
 }
 
 /**
@@ -621,6 +630,10 @@ static void emit_be_MemPerm(const ir_node *node)
 
 static void emit_sparc_Return(const ir_node *node)
 {
+       ir_graph  *irg    = get_irn_irg(node);
+       ir_entity *entity = get_irg_entity(irg);
+       ir_type   *type   = get_entity_type(entity);
+
        const char *destreg = "%o7";
 
        /* hack: we don't explicitely model register changes because of the
@@ -632,7 +645,11 @@ static void emit_sparc_Return(const ir_node *node)
        }
        be_emit_cstring("\tjmp ");
        be_emit_string(destreg);
-       be_emit_cstring("+8");
+       if (get_method_calling_convention(type) & cc_compound_ret) {
+               be_emit_cstring("+12");
+       } else {
+               be_emit_cstring("+8");
+       }
        be_emit_finish_line_gas(node);
        fill_delay_slot();
 }
@@ -848,8 +865,8 @@ static const arch_register_t *get_next_fp_reg(const arch_register_t *reg)
 static void emit_be_Copy(const ir_node *node)
 {
        ir_mode               *mode    = get_irn_mode(node);
-       const arch_register_t *src_reg = get_in_reg(node, 0);
-       const arch_register_t *dst_reg = arch_irn_get_register(node, 0);
+       const arch_register_t *src_reg = arch_get_irn_register_in(node, 0);
+       const arch_register_t *dst_reg = arch_get_irn_register_out(node, 0);
 
        if (src_reg == dst_reg)
                return;
@@ -909,7 +926,8 @@ static void sparc_register_emitters(void)
        set_emitter(op_sparc_Call,      emit_sparc_Call);
        set_emitter(op_sparc_fbfcc,     emit_sparc_fbfcc);
        set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr);
-       set_emitter(op_sparc_Mulh,      emit_sparc_Mulh);
+       set_emitter(op_sparc_SMulh,     emit_sparc_Mulh);
+       set_emitter(op_sparc_UMulh,     emit_sparc_Mulh);
        set_emitter(op_sparc_Return,    emit_sparc_Return);
        set_emitter(op_sparc_SDiv,      emit_sparc_SDiv);
        set_emitter(op_sparc_SwitchJmp, emit_sparc_SwitchJmp);
@@ -1028,9 +1046,6 @@ void sparc_emit_routine(ir_graph *irg)
        size_t      i;
        size_t      n;
 
-       be_gas_elf_type_char      = '#';
-       be_gas_object_file_format = OBJECT_FILE_FORMAT_ELF_SPARC;
-
        heights = heights_new(irg);
 
        /* register all emitter functions */