Commit cd1ba320 authored by Matthias Braun's avatar Matthias Braun
Browse files

update TEMPLATE backend

Still broken for anything except int f(void) { return 0; } though...
parent 16a8ee53
...@@ -211,6 +211,21 @@ Jmp => { ...@@ -211,6 +211,21 @@ Jmp => {
mode => "mode_X", mode => "mode_X",
}, },
Start => {
state => "pinned",
reg_req => { in => [], out => [ "sp:I|S", "none" ] },
outs => [ "stack", "M" ],
ins => [],
},
Return => {
state => "pinned",
op_flags => [ "cfopcode" ],
ins => [ "stack", "mem" ],
reg_req => { in => [ "sp", "none", ], out => [] },
mode => "mode_X",
},
# Load / Store # Load / Store
Load => { Load => {
......
...@@ -48,6 +48,8 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) ...@@ -48,6 +48,8 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
typedef ir_node* (*new_binop_func)(dbg_info *dbgi, ir_node *block, typedef ir_node* (*new_binop_func)(dbg_info *dbgi, ir_node *block,
ir_node *left, ir_node *right); ir_node *left, ir_node *right);
static ir_mode *gp_regs_mode;
static ir_node *transform_binop(ir_node *node, new_binop_func new_func) static ir_node *transform_binop(ir_node *node, new_binop_func new_func)
{ {
ir_node *block = get_nodes_block(node); ir_node *block = get_nodes_block(node);
...@@ -216,6 +218,28 @@ static ir_node *gen_Jmp(ir_node *node) ...@@ -216,6 +218,28 @@ static ir_node *gen_Jmp(ir_node *node)
return new_bd_TEMPLATE_Jmp(dbgi, new_block); return new_bd_TEMPLATE_Jmp(dbgi, new_block);
} }
static ir_node *gen_Start(ir_node *node)
{
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *block = get_nodes_block(node);
ir_node *new_block = be_transform_node(block);
return new_bd_TEMPLATE_Start(dbgi, new_block);
}
static ir_node *gen_Return(ir_node *node)
{
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *block = get_nodes_block(node);
ir_node *new_block = be_transform_node(block);
ir_node *mem = get_Return_mem(node);
ir_node *new_mem = be_transform_node(mem);
ir_graph *irg = get_irn_irg(node);
ir_node *sp = get_irg_frame(irg);
return new_bd_TEMPLATE_Return(dbgi, new_block, sp, new_mem);
}
/** /**
* returns true if mode should be stored in a general purpose register * returns true if mode should be stored in a general purpose register
*/ */
...@@ -251,26 +275,62 @@ static ir_node *gen_Phi(ir_node *node) ...@@ -251,26 +275,62 @@ static ir_node *gen_Phi(ir_node *node)
return phi; return phi;
} }
static ir_node *gen_Proj_Start(ir_node *node)
{
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *block = get_nodes_block(node);
ir_node *new_block = be_transform_node(block);
ir_node *start = get_Proj_pred(node);
ir_node *new_start = be_transform_node(start);
long pn = get_Proj_proj(node);
switch ((pn_Start) pn) {
case pn_Start_X_initial_exec:
return new_bd_TEMPLATE_Jmp(dbgi, new_block);
case pn_Start_M:
return new_rd_Proj(dbgi, new_start, mode_M, pn_TEMPLATE_Start_M);
case pn_Start_T_args:
return new_r_Bad(get_irn_irg(block), mode_T);
case pn_Start_P_frame_base:
return new_rd_Proj(dbgi, new_start, gp_regs_mode, pn_TEMPLATE_Start_stack);
}
panic("unexpected Start proj %ld\n", pn);
}
static ir_node *gen_Proj(ir_node *node)
{
ir_node *pred = get_Proj_pred(node);
switch (get_irn_opcode(pred)) {
case iro_Start: return gen_Proj_Start(node);
default:
panic("code selection can't handle Proj after %+F\n", pred);
}
}
static void TEMPLATE_register_transformers(void) static void TEMPLATE_register_transformers(void)
{ {
be_start_transform_setup(); be_start_transform_setup();
be_set_transform_function(op_Add, gen_Add); be_set_transform_function(op_Add, gen_Add);
be_set_transform_function(op_And, gen_And); be_set_transform_function(op_And, gen_And);
be_set_transform_function(op_Const, gen_Const); be_set_transform_function(op_Const, gen_Const);
be_set_transform_function(op_Div, gen_Div); be_set_transform_function(op_Div, gen_Div);
be_set_transform_function(op_Eor, gen_Eor); be_set_transform_function(op_Eor, gen_Eor);
be_set_transform_function(op_Jmp, gen_Jmp); be_set_transform_function(op_Jmp, gen_Jmp);
be_set_transform_function(op_Load, gen_Load); be_set_transform_function(op_Load, gen_Load);
be_set_transform_function(op_Minus, gen_Minus); be_set_transform_function(op_Minus, gen_Minus);
be_set_transform_function(op_Mul, gen_Mul); be_set_transform_function(op_Mul, gen_Mul);
be_set_transform_function(op_Not, gen_Not); be_set_transform_function(op_Not, gen_Not);
be_set_transform_function(op_Or, gen_Or); be_set_transform_function(op_Or, gen_Or);
be_set_transform_function(op_Phi, gen_Phi); be_set_transform_function(op_Proj, gen_Proj);
be_set_transform_function(op_Shl, gen_Shl); be_set_transform_function(op_Phi, gen_Phi);
be_set_transform_function(op_Shr, gen_Shr); be_set_transform_function(op_Return, gen_Return);
be_set_transform_function(op_Store, gen_Store); be_set_transform_function(op_Shl, gen_Shl);
be_set_transform_function(op_Sub, gen_Sub); be_set_transform_function(op_Shr, gen_Shr);
be_set_transform_function(op_Start, gen_Start);
be_set_transform_function(op_Store, gen_Store);
be_set_transform_function(op_Sub, gen_Sub);
} }
/** /**
...@@ -278,6 +338,8 @@ static void TEMPLATE_register_transformers(void) ...@@ -278,6 +338,8 @@ static void TEMPLATE_register_transformers(void)
*/ */
void TEMPLATE_transform_graph(ir_graph *irg) void TEMPLATE_transform_graph(ir_graph *irg)
{ {
gp_regs_mode = TEMPLATE_reg_classes[CLASS_TEMPLATE_gp].mode;
TEMPLATE_register_transformers(); TEMPLATE_register_transformers();
be_transform_graph(irg, NULL); be_transform_graph(irg, NULL);
} }
......
...@@ -144,7 +144,7 @@ static TEMPLATE_isa_t TEMPLATE_isa_template = { ...@@ -144,7 +144,7 @@ static TEMPLATE_isa_t TEMPLATE_isa_template = {
NULL, /* main environment */ NULL, /* main environment */
7, /* costs for a spill instruction */ 7, /* costs for a spill instruction */
5, /* costs for a reload instruction */ 5, /* costs for a reload instruction */
false, /* no custom abi handling */ true, /* no custom abi handling */
}, },
}; };
......
# Firm node specifications
# The comments are in (standard python) restructured text format and are used
# to generate documentation.
from spec_util import abstract, setnodedefaults from spec_util import abstract, setnodedefaults
class Op(object): class Op(object):
...@@ -85,7 +88,33 @@ class And(Binop): ...@@ -85,7 +88,33 @@ class And(Binop):
flags = [ "commutative" ] flags = [ "commutative" ]
class ASM(Op): class ASM(Op):
"""executes assembler fragments of the target machine""" """executes assembler fragments of the target machine.
The node contains a template for an assembler snippet. The compiler will
replace occurences of %0 to %9 with input/output registers,
%% with a single % char. Some backends allow additional specifiers (for
example %w3, %l3, %h3 on x86 to get a 16bit, 8hit low, 8bit high part
of a register).
After the replacements the text is emitted into the final assembly.
The clobber list contains names of registers which have an undefined value
after the assembler instruction is executed; it may also contain 'memory'
or 'cc' if global state/memory changes or the condition code registers
(some backends implicitely set cc, memory clobbers on all ASM statements).
Example (an i386 instruction)::
ASM(text="btsl %1, %0",
input_constraints = ["=m", "r"],
clobbers = ["cc"])
As there are no output, the %0 references the first input which is just an
address which the asm operation writes to. %1 references to an input which
is passed as a register. The condition code register has an unknown value
after the instruction.
(This format is inspired by the gcc extended asm syntax)
"""
mode = "mode_T" mode = "mode_T"
arity = "variable" arity = "variable"
flags = [ "keep", "uses_memory" ] flags = [ "keep", "uses_memory" ]
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment