amd64: implemented Store, Mul and Sub.
authorRobin Redeker <rredeker@ipd.info.uni-karlsruhe.de>
Mon, 28 Jun 2010 13:08:17 +0000 (13:08 +0000)
committerRobin Redeker <rredeker@ipd.info.uni-karlsruhe.de>
Mon, 28 Jun 2010 13:08:17 +0000 (13:08 +0000)
[r27667]

ir/be/amd64/amd64_emitter.c
ir/be/amd64/amd64_emitter.h
ir/be/amd64/amd64_spec.pl
ir/be/amd64/amd64_transform.c
ir/be/amd64/bearch_amd64.c

index edc9333..4a48d3e 100644 (file)
@@ -115,6 +115,12 @@ static const arch_register_t *get_out_reg(const ir_node *node, int pos)
  * |_|                                       |_|
  *************************************************************/
 
+void amd64_emit_register(const arch_register_t *reg)
+{
+       be_emit_char('%');
+       be_emit_string(arch_register_get_name(reg));
+}
+
 void amd64_emit_immediate(const ir_node *node)
 {
        const amd64_attr_t *attr = get_amd64_attr_const (node);
@@ -124,16 +130,12 @@ void amd64_emit_immediate(const ir_node *node)
 
 void amd64_emit_source_register(const ir_node *node, int pos)
 {
-       const arch_register_t *reg = get_in_reg(node, pos);
-       be_emit_char('%');
-       be_emit_string(arch_register_get_name(reg));
+       amd64_emit_register(get_in_reg(node, pos));
 }
 
 void amd64_emit_dest_register(const ir_node *node, int pos)
 {
-       const arch_register_t *reg = get_out_reg(node, pos);
-       be_emit_char('%');
-       be_emit_string(arch_register_get_name(reg));
+       amd64_emit_register(get_out_reg(node, pos));
 }
 
 /**
@@ -367,18 +369,41 @@ static void emit_amd64_FrameAddr(const ir_node *irn)
        const amd64_SymConst_attr_t *attr = get_irn_generic_attr_const(irn);
 
        be_emit_cstring("\tmov ");
-       amd64_emit_dest_register(irn, 0);
-       be_emit_cstring(", ");
        amd64_emit_source_register(irn, 0);
+       be_emit_cstring(", ");
+       amd64_emit_dest_register(irn, 0);
        be_emit_finish_line_gas(irn);
 
        be_emit_cstring("\tadd ");
-       amd64_emit_dest_register(irn, 0);
-       be_emit_cstring(", ");
        be_emit_irprintf("$0x%X", attr->fp_offset);
+       be_emit_cstring(", ");
+       amd64_emit_dest_register(irn, 0);
        be_emit_finish_line_gas(irn);
 }
 
+/**
+ * Emits code to increase stack pointer.
+ */
+static void emit_be_IncSP(const ir_node *node)
+{
+       int offs = be_get_IncSP_offset(node);
+
+       if (offs == 0)
+               return;
+
+       if (offs > 0) {
+               be_emit_irprintf("\tsub ");
+               amd64_emit_dest_register(node, 0);
+               be_emit_irprintf(", $%u", offs);
+               be_emit_finish_line_gas(node);
+       } else {
+               be_emit_irprintf("\tadd ");
+               amd64_emit_dest_register(node, 0);
+               be_emit_irprintf(", $%u", -offs);
+               be_emit_finish_line_gas(node);
+       }
+}
+
 /**
  * Emits code for a return.
  */
@@ -388,6 +413,51 @@ static void emit_be_Return(const ir_node *node)
        be_emit_finish_line_gas(node);
 }
 
+
+static void emit_amd64_binop_op(const ir_node *irn, int second_op)
+{
+       if (irn->op == op_amd64_Add) {
+               be_emit_cstring("\tadd ");
+       } else if (irn->op == op_amd64_Mul) {
+               be_emit_cstring("\tmul ");
+       } else if (irn->op == op_amd64_Sub) {
+               be_emit_cstring("\tsub ");
+       }
+
+       amd64_emit_dest_register(irn, 0);
+       be_emit_cstring(", ");
+       amd64_emit_source_register(irn, second_op);
+       be_emit_finish_line_gas(irn);
+}
+
+/**
+ * Emits an arithmetic operation that handles arbitraty input registers.
+ */
+static void emit_amd64_binop(const ir_node *irn)
+{
+       const arch_register_t *reg_s1 = get_in_reg(irn, 0);
+       const arch_register_t *reg_s2 = get_in_reg(irn, 1);
+       const arch_register_t *reg_d1 = get_out_reg(irn, 0);
+
+       int second_op = 0;
+
+       if (reg_d1 != reg_s1 && reg_d1 != reg_s2) {
+               be_emit_cstring("\tmov ");
+               amd64_emit_register(reg_s1);
+               be_emit_cstring(", ");
+               amd64_emit_register(reg_d1);
+               be_emit_finish_line_gas(irn);
+               second_op = 1;
+
+       } else if (reg_d1 == reg_s2 && reg_d1 != reg_s1) {
+               second_op = 0;
+
+       }
+
+       emit_amd64_binop_op(irn, second_op);
+
+}
+
 /**
  * The type of a emitter function.
  */
@@ -420,11 +490,14 @@ static void amd64_register_emitters(void)
        set_emitter(op_be_Return,        emit_be_Return);
        set_emitter(op_be_Call,          emit_be_Call);
        set_emitter(op_be_Copy,          emit_be_Copy);
+       set_emitter(op_be_IncSP,         emit_be_IncSP);
+
+       set_emitter(op_amd64_Add,        emit_amd64_binop);
+       set_emitter(op_amd64_Mul,        emit_amd64_binop);
 
        set_emitter(op_be_Start,         emit_nothing);
        set_emitter(op_be_Keep,          emit_nothing);
        set_emitter(op_be_Barrier,       emit_nothing);
-       set_emitter(op_be_IncSP,         emit_nothing);
        set_emitter(op_Phi,              emit_nothing);
 }
 
index 7d21ea9..c0142ff 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "bearch_amd64_t.h"
 
+void amd64_emit_register(const arch_register_t *reg);
 void amd64_emit_source_register(const ir_node *node, int pos);
 void amd64_emit_dest_register(const ir_node *node, int pos);
 void amd64_emit_immediate(const ir_node *node);
index 147dab0..1699581 100644 (file)
@@ -203,22 +203,43 @@ Push => {
 #      units     => [ "GP" ],
 },
 Add => {
+       op_flags   => "C",
        irn_flags  => "R",
        state      => "exc_pinned",
        reg_req    => { in => [ "gp", "gp" ],
                        out => [ "gp" ] },
        in         => [ "left", "right" ],
-       emit       => ". mov %D1, %S2\n"
-                     . ". add %D1, %S1\n",
        outs       => [ "res" ],
        mode       => $mode_gp,
+       modified_flags => 1,
+},
+Mul => {
+       op_flags   => "C",
+       irn_flags  => "R",
+       state      => "exc_pinned",
+       reg_req    => { in => [ "gp", "gp" ],
+                       out => [ "gp" ] },
+       in         => [ "left", "right" ],
+       outs       => [ "res" ],
+       mode       => $mode_gp,
+       modified_flags => 1,
+},
+Sub => {
+       irn_flags  => "R",
+       state      => "exc_pinned",
+       reg_req    => { in => [ "gp", "gp" ],
+                       out => [ "gp" ] },
+       in         => [ "left", "right" ],
+       outs       => [ "res" ],
+       mode       => $mode_gp,
+       modified_flags => 1,
 },
 Immediate => {
        op_flags  => "c",
        attr      => "unsigned imm_value",
        init_attr => "attr->ext.imm_value = imm_value;",
        reg_req   => { out => [ "gp" ] },
-       emit      => '. movq %D1, %C',
+       emit      => '. mov %C, %D1',
        mode      => $mode_gp,
 },
 SymConst => {
@@ -275,7 +296,7 @@ Load => {
                       out => [ "gp", "none" ] },
        ins       => [ "ptr", "mem" ],
        outs      => [ "res",  "M" ],
-       emit      => ". lea %D1, [%S1]"
+       emit      => ". mov (%S1), %D1"
 },
 FrameAddr => {
        op_flags  => "c",
@@ -286,15 +307,15 @@ FrameAddr => {
        attr_type => "amd64_SymConst_attr_t",
        mode      => $mode_gp,
 },
-#Store => {
-#      op_flags  => "L|F",
-#      state     => "exc_pinned",
-#      reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none", "none" ] },
-#      ins       => [ "base", "index", "mem", "val" ],
-#      outs      => [ "M", "X_exc" ],
-#      mode      => "mode_M",
-#},
-
+Store => {
+       op_flags  => "L|F",
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
+       ins       => [ "ptr", "val", "mem" ],
+       outs      => [ "M" ],
+       mode      => "mode_M",
+       emit      => ". mov (%S1), %S2"
+},
 
 #NoReg_GP => {
 #      state     => "pinned",
index 1c6e588..b2b2c72 100644 (file)
@@ -358,6 +358,34 @@ static ir_node *gen_Conv(ir_node *node)
        }
 }
 
+/**
+ * Transforms a Store.
+ *
+ * @return the created AMD64 Store node
+ */
+static ir_node *gen_Store(ir_node *node)
+{
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *ptr      = get_Store_ptr(node);
+       ir_node  *new_ptr  = be_transform_node(ptr);
+       ir_node  *mem      = get_Store_mem(node);
+       ir_node  *new_mem  = be_transform_node(mem);
+       ir_node  *val      = get_Store_value(node);
+       ir_node  *new_val  = be_transform_node(val);
+       ir_mode  *mode     = get_irn_mode(val);
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       ir_node *new_store = NULL;
+
+       if (mode_is_float(mode)) {
+               panic("Float not supported yet");
+       } else {
+               assert(mode_is_data(mode) && "unsupported mode for Store");
+               new_store = new_bd_amd64_Store(dbgi, block, new_ptr, new_val, new_mem);
+       }
+       set_irn_pinned(new_store, get_irn_pinned(node));
+       return new_store;
+}
+
 /**
  * Transforms a Load.
  *
@@ -531,6 +559,7 @@ static void amd64_register_transformers(void)
        set_transformer(op_Cond,         gen_Cond);
        set_transformer(op_Phi,          gen_Phi);
        set_transformer(op_Load,         gen_Load);
+       set_transformer(op_Store,        gen_Store);
        set_transformer(op_Proj,         gen_Proj);
 }
 
index 63e4b5d..5783ea3 100644 (file)
@@ -402,6 +402,21 @@ static const be_abi_callbacks_t amd64_abi_callbacks = {
        amd64_abi_epilogue,
 };
 
+static const arch_register_t *gpreg_param_reg_std[] = {
+       &amd64_gp_regs[REG_RDI],
+       &amd64_gp_regs[REG_RSI],
+       &amd64_gp_regs[REG_RDX],
+       &amd64_gp_regs[REG_RCX],
+       &amd64_gp_regs[REG_R8],
+       &amd64_gp_regs[REG_R9],
+};
+
+static const arch_register_t *amd64_get_RegParam_reg(int n)
+{
+       assert(n < 6 && n >=0 && "register param > 6 requested");
+       return gpreg_param_reg_std[n];
+}
+
 /**
  * Get the ABI restrictions for procedure calls.
  * @param self        The this pointer.
@@ -434,11 +449,9 @@ static void amd64_get_call_abi(const void *self, ir_type *method_type,
                mode = get_type_mode(tp);
                //d// printf ("MODE %p %p XX %d\n", mode, mode_Iu, i);
 
-               if (!no_reg && (i == 0 || i == 1) && mode == mode_Iu) {
+               if (!no_reg && i < 6 && mode_is_data (mode)) {
                        //d// printf("TEST%d\n", i);
-                       be_abi_call_param_reg(abi, i,
-                                             i == 0 ? &amd64_gp_regs[REG_RDI]
-                                                    : &amd64_gp_regs[REG_RSI],
+                       be_abi_call_param_reg(abi, i, amd64_get_RegParam_reg (i),
                                              ABI_CONTEXT_BOTH);
                /* default: all parameters on stack */
                } else {