* |_| |_|
*************************************************************/
+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);
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));
}
/**
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.
*/
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.
*/
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);
}
#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);
# 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 => {
out => [ "gp", "none" ] },
ins => [ "ptr", "mem" ],
outs => [ "res", "M" ],
- emit => ". lea %D1, [%S1]"
+ emit => ". mov (%S1), %D1"
},
FrameAddr => {
op_flags => "c",
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",
}
}
+/**
+ * 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.
*
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);
}
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.
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 {