From fecb5663e86ee6a1db64195057ed384514404172 Mon Sep 17 00:00:00 2001 From: Robin Redeker Date: Mon, 28 Jun 2010 13:08:17 +0000 Subject: [PATCH] amd64: implemented Store, Mul and Sub. [r27667] --- ir/be/amd64/amd64_emitter.c | 95 +++++++++++++++++++++++++++++++---- ir/be/amd64/amd64_emitter.h | 1 + ir/be/amd64/amd64_spec.pl | 47 ++++++++++++----- ir/be/amd64/amd64_transform.c | 29 +++++++++++ ir/be/amd64/bearch_amd64.c | 21 ++++++-- 5 files changed, 165 insertions(+), 28 deletions(-) diff --git a/ir/be/amd64/amd64_emitter.c b/ir/be/amd64/amd64_emitter.c index edc933309..4a48d3ec3 100644 --- a/ir/be/amd64/amd64_emitter.c +++ b/ir/be/amd64/amd64_emitter.c @@ -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); } diff --git a/ir/be/amd64/amd64_emitter.h b/ir/be/amd64/amd64_emitter.h index 7d21ea99b..c0142ff09 100644 --- a/ir/be/amd64/amd64_emitter.h +++ b/ir/be/amd64/amd64_emitter.h @@ -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); diff --git a/ir/be/amd64/amd64_spec.pl b/ir/be/amd64/amd64_spec.pl index 147dab059..1699581fb 100644 --- a/ir/be/amd64/amd64_spec.pl +++ b/ir/be/amd64/amd64_spec.pl @@ -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", diff --git a/ir/be/amd64/amd64_transform.c b/ir/be/amd64/amd64_transform.c index 1c6e588ba..b2b2c7232 100644 --- a/ir/be/amd64/amd64_transform.c +++ b/ir/be/amd64/amd64_transform.c @@ -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); } diff --git a/ir/be/amd64/bearch_amd64.c b/ir/be/amd64/bearch_amd64.c index 63e4b5df9..5783ea31f 100644 --- a/ir/be/amd64/bearch_amd64.c +++ b/ir/be/amd64/bearch_amd64.c @@ -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 { -- 2.20.1