Commit aa5c48c2 authored by Hannes Rapp's avatar Hannes Rapp
Browse files

[r27015]

parent 4f644c28
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
#include "gen_sparc_regalloc_if.h" #include "gen_sparc_regalloc_if.h"
#include "sparc_transform.h" #include "sparc_transform.h"
#include "sparc_emitter.h" #include "sparc_emitter.h"
#include "sparc_map_regs.h"
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
...@@ -74,10 +75,22 @@ static arch_irn_class_t sparc_classify(const ir_node *irn) ...@@ -74,10 +75,22 @@ static arch_irn_class_t sparc_classify(const ir_node *irn)
return 0; return 0;
} }
static ir_entity *sparc_get_frame_entity(const ir_node *node) static ir_entity *sparc_get_frame_entity(const ir_node *irn)
{ {
(void) node; const sparc_attr_t *attr = get_sparc_attr_const(irn);
/* TODO: return the ir_entity assigned to the frame */
if (is_sparc_FrameAddr(irn)) {
const sparc_symconst_attr_t *attr = get_irn_generic_attr_const(irn);
return attr->entity;
}
if (attr->is_load_store) {
const sparc_load_store_attr_t *load_store_attr = get_sparc_load_store_attr_const(irn);
if (load_store_attr->is_frame_entity) {
return load_store_attr->entity;
}
}
return NULL; return NULL;
} }
...@@ -85,6 +98,7 @@ static void sparc_set_frame_entity(ir_node *node, ir_entity *ent) ...@@ -85,6 +98,7 @@ static void sparc_set_frame_entity(ir_node *node, ir_entity *ent)
{ {
(void) node; (void) node;
(void) ent; (void) ent;
panic("sparc_set_frame_entity() called. This should not happen.");
/* TODO: set the ir_entity assigned to the frame */ /* TODO: set the ir_entity assigned to the frame */
} }
...@@ -94,9 +108,14 @@ static void sparc_set_frame_entity(ir_node *node, ir_entity *ent) ...@@ -94,9 +108,14 @@ static void sparc_set_frame_entity(ir_node *node, ir_entity *ent)
*/ */
static void sparc_set_frame_offset(ir_node *irn, int offset) static void sparc_set_frame_offset(ir_node *irn, int offset)
{ {
(void) irn; if (is_sparc_FrameAddr(irn)) {
(void) offset; sparc_symconst_attr_t *attr = get_irn_generic_attr(irn);
/* TODO: correct offset if irn accesses the stack */ attr->fp_offset += offset;
} else {
sparc_load_store_attr_t *attr = get_sparc_load_store_attr(irn);
assert(attr->base.is_load_store);
attr->offset += offset;
}
} }
static int sparc_get_sp_bias(const ir_node *irn) static int sparc_get_sp_bias(const ir_node *irn)
...@@ -174,10 +193,86 @@ static void sparc_before_ra(void *self) ...@@ -174,10 +193,86 @@ static void sparc_before_ra(void *self)
be_sched_fix_flags(cg->birg, &sparc_reg_classes[CLASS_sparc_flags], &sparc_flags_remat); be_sched_fix_flags(cg->birg, &sparc_reg_classes[CLASS_sparc_flags], &sparc_flags_remat);
} }
/**
* transform reload node => load
*/
static void transform_Reload(ir_node *node)
{
ir_graph *irg = get_irn_irg(node);
ir_node *block = get_nodes_block(node);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *ptr = get_irg_frame(irg);
ir_node *mem = get_irn_n(node, be_pos_Reload_mem);
ir_mode *mode = get_irn_mode(node);
ir_entity *entity = be_get_frame_entity(node);
const arch_register_t *reg;
ir_node *proj;
ir_node *load;
ir_node *sched_point = sched_prev(node);
load = new_bd_sparc_Load(dbgi, block, ptr, mem, mode, entity, false, 0, true);
sched_add_after(sched_point, load);
sched_remove(node);
proj = new_rd_Proj(dbgi, block, load, mode, pn_sparc_Load_res);
reg = arch_get_irn_register(node);
arch_set_irn_register(proj, reg);
exchange(node, proj);
}
/**
* transform spill node => store
*/
static void transform_Spill(ir_node *node)
{
ir_graph *irg = get_irn_irg(node);
ir_node *block = get_nodes_block(node);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *ptr = get_irg_frame(irg);
ir_node *mem = new_NoMem();
ir_node *val = get_irn_n(node, be_pos_Spill_val);
ir_mode *mode = get_irn_mode(val);
ir_entity *entity = be_get_frame_entity(node);
ir_node *sched_point;
ir_node *store;
sched_point = sched_prev(node);
store = new_bd_sparc_Store(dbgi, block, ptr, val, mem, mode, entity, false, 0, true);
sched_remove(node);
sched_add_after(sched_point, store);
exchange(node, store);
}
/**
* walker to transform be_Spill and be_Reload nodes
*/
static void sparc_after_ra_walker(ir_node *block, void *data)
{
ir_node *node, *prev;
(void) data;
for (node = sched_last(block); !sched_is_begin(node); node = prev) {
prev = sched_prev(node);
if (be_is_Reload(node)) {
transform_Reload(node);
} else if (be_is_Spill(node)) {
transform_Spill(node);
}
}
}
static void sparc_after_ra(void *self) static void sparc_after_ra(void *self)
{ {
(void) self; sparc_code_gen_t *cg = self;
/* Some stuff you need to do immediatly after register allocation */ be_coalesce_spillslots(cg->birg);
irg_block_walk_graph(cg->irg, NULL, sparc_after_ra_walker, NULL);
} }
...@@ -428,13 +523,17 @@ void sparc_get_call_abi(const void *self, ir_type *method_type, ...@@ -428,13 +523,17 @@ void sparc_get_call_abi(const void *self, ir_type *method_type,
be_abi_call_set_flags(abi, call_flags, &sparc_abi_callbacks); be_abi_call_set_flags(abi, call_flags, &sparc_abi_callbacks);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
/* TODO: implement register parameter: */
/* reg = get reg for param i; */ /* reg = get reg for param i; */
/* be_abi_call_param_reg(abi, i, reg); */ /* be_abi_call_param_reg(abi, i, reg); */
/* default: all parameters on stack */
tp = get_method_param_type(method_type, i); /* pass args 0-5 via registers, remaining via stack */
mode = get_type_mode(tp); if (i < 6) {
be_abi_call_param_stack(abi, i, mode, 4, 0, 0); be_abi_call_param_reg(abi, i, sparc_get_RegParam_reg(i));
} else {
tp = get_method_param_type(method_type, i);
mode = get_type_mode(tp);
be_abi_call_param_stack(abi, i, mode, 4, 0, 0);
}
} }
/* TODO: set correct return register */ /* TODO: set correct return register */
......
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief Register mapping for firm nodes. Stolen from bearch_firm :)
* @author Hannes Rapp
* @version $Id: sparc_map_regs.c 22754 2008-10-11 20:49:37Z matze $
*/
#include "config.h"
#include <stdlib.h>
#include "sparc_map_regs.h"
#include "sparc_new_nodes.h"
#include "gen_sparc_regalloc_if.h"
static const arch_register_t *gp_param_regs[] = {
&sparc_gp_regs[REG_O0],
&sparc_gp_regs[REG_O1],
&sparc_gp_regs[REG_O2],
&sparc_gp_regs[REG_O3],
&sparc_gp_regs[REG_O4],
&sparc_gp_regs[REG_O5],
};
const arch_register_t *sparc_get_RegParam_reg(int n) {
assert(n < 6 && n >=0 && "trying to get register for param >= 6");
return gp_param_regs[n];
}
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief declarations for SPARC register allocation
* @author Hannes Rapp
* @version $Id: sparc_map_regs.h 26317 2009-08-05 10:53:46Z matze $
*/
#ifndef FIRM_BE_SPARC_SPARC_MAP_REGS_H
#define FIRM_BE_SPARC_SPARC_MAP_REGS_H
#include "irnode.h"
#include "set.h"
#include "../bearch.h"
#include "sparc_nodes_attr.h"
const arch_register_t *sparc_get_RegParam_reg(int n);
#endif
...@@ -93,25 +93,42 @@ static void sparc_set_attr_imm(ir_node *res, int immediate_value) ...@@ -93,25 +93,42 @@ static void sparc_set_attr_imm(ir_node *res, int immediate_value)
attr->immediate_value = immediate_value; attr->immediate_value = immediate_value;
} }
static void set_sparc_jmp_cond_proj_num(ir_node *node, int proj_num) void set_sparc_jmp_cond_proj_num(ir_node *node, int proj_num)
{ {
sparc_jmp_cond_attr_t *attr = get_sparc_jmp_cond_attr(node); sparc_jmp_cond_attr_t *attr = get_sparc_jmp_cond_attr(node);
attr->proj_num = proj_num; attr->proj_num = proj_num;
} }
static void set_sparc_jmp_switch_n_projs(ir_node *node, int n_projs) void set_sparc_jmp_switch_n_projs(ir_node *node, int n_projs)
{ {
sparc_jmp_switch_attr_t *attr = get_sparc_jmp_switch_attr(node); sparc_jmp_switch_attr_t *attr = get_sparc_jmp_switch_attr(node);
attr->n_projs = n_projs; attr->n_projs = n_projs;
} }
static void set_sparc_jmp_switch_default_proj_num(ir_node *node, long def_proj_num) void set_sparc_jmp_switch_default_proj_num(ir_node *node, long def_proj_num)
{ {
sparc_jmp_switch_attr_t *attr = get_sparc_jmp_switch_attr(node); sparc_jmp_switch_attr_t *attr = get_sparc_jmp_switch_attr(node);
attr->default_proj_num = def_proj_num; attr->default_proj_num = def_proj_num;
} }
int get_sparc_jmp_cond_proj_num(const ir_node *node) {
const sparc_jmp_cond_attr_t *attr = get_sparc_jmp_cond_attr_const(node);
return attr->proj_num;
}
int get_sparc_jmp_switch_n_projs(const ir_node *node) {
const sparc_jmp_switch_attr_t *attr = get_sparc_jmp_switch_attr_const(node);
return attr->n_projs;
}
long get_sparc_jmp_switch_default_proj_num(const ir_node *node) {
const sparc_jmp_switch_attr_t *attr = get_sparc_jmp_switch_attr_const(node);
return attr->default_proj_num;
}
/* ATTRIBUTE GETTERS */ /* ATTRIBUTE GETTERS */
sparc_attr_t *get_sparc_attr(ir_node *node) sparc_attr_t *get_sparc_attr(ir_node *node)
{ {
...@@ -297,37 +314,73 @@ static int cmp_attr_sparc(ir_node *a, ir_node *b) ...@@ -297,37 +314,73 @@ static int cmp_attr_sparc(ir_node *a, ir_node *b)
{ {
const sparc_attr_t *attr_a = get_sparc_attr_const(a); const sparc_attr_t *attr_a = get_sparc_attr_const(a);
const sparc_attr_t *attr_b = get_sparc_attr_const(b); const sparc_attr_t *attr_b = get_sparc_attr_const(b);
(void) attr_a;
(void) attr_b;
return 0; return attr_a->immediate_value != attr_b->immediate_value
|| attr_a->is_load_store != attr_b->is_load_store;
} }
/* CUSTOM ATTRIBUTE CMP FUNCTIONS */ /* CUSTOM ATTRIBUTE CMP FUNCTIONS */
static int cmp_attr_sparc_load_store(ir_node *a, ir_node *b) static int cmp_attr_sparc_load_store(ir_node *a, ir_node *b)
{ {
return 0; const sparc_load_store_attr_t *attr_a = get_sparc_load_store_attr_const(a);
const sparc_load_store_attr_t *attr_b = get_sparc_load_store_attr_const(b);
if (cmp_attr_sparc(a, b))
return 1;
return attr_a->entity != attr_b->entity
|| attr_a->entity_sign != attr_b->entity_sign
|| attr_a->is_frame_entity != attr_b->is_frame_entity
|| attr_a->load_store_mode != attr_b->load_store_mode
|| attr_a->offset != attr_b->offset;
} }
static int cmp_attr_sparc_symconst(ir_node *a, ir_node *b) static int cmp_attr_sparc_symconst(ir_node *a, ir_node *b)
{ {
return 0; const sparc_symconst_attr_t *attr_a = get_sparc_symconst_attr_const(a);
const sparc_symconst_attr_t *attr_b = get_sparc_symconst_attr_const(b);
if (cmp_attr_sparc(a, b))
return 1;
return attr_a->entity != attr_b->entity
|| attr_a->fp_offset != attr_b->fp_offset;
} }
static int cmp_attr_sparc_jmp_cond(ir_node *a, ir_node *b) static int cmp_attr_sparc_jmp_cond(ir_node *a, ir_node *b)
{ {
return 0; const sparc_jmp_cond_attr_t *attr_a = get_sparc_jmp_cond_attr_const(a);
const sparc_jmp_cond_attr_t *attr_b = get_sparc_jmp_cond_attr_const(b);
if (cmp_attr_sparc(a, b))
return 1;
return attr_a->proj_num != attr_b->proj_num;
} }
static int cmp_attr_sparc_jmp_switch(ir_node *a, ir_node *b) static int cmp_attr_sparc_jmp_switch(ir_node *a, ir_node *b)
{ {
return 0; const sparc_jmp_switch_attr_t *attr_a = get_sparc_jmp_switch_attr_const(a);
const sparc_jmp_switch_attr_t *attr_b = get_sparc_jmp_switch_attr_const(b);
if (cmp_attr_sparc(a, b))
return 1;
return attr_a->default_proj_num != attr_b->default_proj_num
|| attr_a->n_projs != attr_b->n_projs;
} }
static int cmp_attr_sparc_cmp(ir_node *a, ir_node *b) static int cmp_attr_sparc_cmp(ir_node *a, ir_node *b)
{ {
return 0; const sparc_cmp_attr_t *attr_a = get_sparc_cmp_attr_const(a);
const sparc_cmp_attr_t *attr_b = get_sparc_cmp_attr_const(b);
if (cmp_attr_sparc(a, b))
return 1;
return attr_a->ins_permuted != attr_b->ins_permuted
|| attr_a->is_unsigned != attr_b->is_unsigned;
} }
/* Include the generated constructor functions */ /* Include the generated constructor functions */
......
...@@ -74,6 +74,38 @@ const arch_register_req_t *get_sparc_in_req(const ir_node *node, int pos); ...@@ -74,6 +74,38 @@ const arch_register_req_t *get_sparc_in_req(const ir_node *node, int pos);
*/ */
void set_sparc_req_in(ir_node *node, const arch_register_req_t *req, int pos); void set_sparc_req_in(ir_node *node, const arch_register_req_t *req, int pos);
/**
* Returns the proj num
*/
int get_sparc_jmp_cond_proj_num(const ir_node *node);
/**
* Sets the proj num
*/
void set_sparc_jmp_cond_proj_num(ir_node *node, int proj_num);
/**
* Returns the number of projs of a SwitchJmp.
*/
int get_sparc_jmp_switch_n_projs(const ir_node *node);
/**
* Sets the number of projs of a SwitchJmp.
*/
void set_sparc_jmp_switch_n_projs(ir_node *node, int n_projs);
/**
* Returns the default_proj_num.
*/
long get_sparc_jmp_switch_default_proj_num(const ir_node *node);
/**
* Sets the default_proj_num.
*/
void set_sparc_jmp_switch_default_proj_num(ir_node *node, long default_proj_num);
/* Include the generated headers */ /* Include the generated headers */
#include "gen_sparc_new_nodes.h" #include "gen_sparc_new_nodes.h"
......
...@@ -107,44 +107,44 @@ $mode_fp = "mode_D"; ...@@ -107,44 +107,44 @@ $mode_fp = "mode_D";
# available SPARC registers: 8 globals, 24 window regs (8 ins, 8 outs, 8 locals) # available SPARC registers: 8 globals, 24 window regs (8 ins, 8 outs, 8 locals)
%reg_classes = ( %reg_classes = (
gp => [ gp => [
{ name => "g0", realname => "r0", type => 4 }, # hardwired 0, behaves like /dev/null { name => "g0", realname => "g0", type => 4 }, # hardwired 0, behaves like /dev/null
{ name => "g1", realname => "r1", type => 1 }, # temp. value { name => "g1", realname => "g1", type => 1 }, # temp. value
{ name => "g2", realname => "r2", type => 1 }, { name => "g2", realname => "g2", type => 1 },
{ name => "g3", realname => "r3", type => 1 }, { name => "g3", realname => "g3", type => 1 },
{ name => "g4", realname => "r4", type => 1 }, { name => "g4", realname => "g4", type => 1 },
{ name => "g5", realname => "r5", type => 1 }, # reserved by SPARC ABI { name => "g5", realname => "g5", type => 4 }, # reserved by SPARC ABI
{ name => "g6", realname => "r6", type => 1 }, # reserved by SPARC ABI { name => "g6", realname => "g6", type => 4 }, # reserved by SPARC ABI
{ name => "g7", realname => "r7", type => 2 }, # reserved by SPARC ABI { name => "g7", realname => "g7", type => 2 }, # reserved by SPARC ABI
# window's out registers # window's out registers
{ name => "o0", realname => "r8", type => 1 }, # param 1 / return value from callee { name => "o0", realname => "o0", type => 1 }, # param 1 / return value from callee
{ name => "o1", realname => "r9", type => 1 }, # param 2 { name => "o1", realname => "o1", type => 1 }, # param 2
{ name => "o2", realname => "r10", type => 1 }, # param 3 { name => "o2", realname => "o2", type => 1 }, # param 3
{ name => "o3", realname => "r11", type => 1 }, # param 4 { name => "o3", realname => "o3", type => 1 }, # param 4
{ name => "o4", realname => "r12", type => 1 }, # param 5 { name => "o4", realname => "o4", type => 1 }, # param 5
{ name => "o5", realname => "r13", type => 1 }, # param 6 { name => "o5", realname => "o5", type => 1 }, # param 6
{ name => "sp", realname => "r14", type => 4 }, # our stackpointer { name => "sp", realname => "sp", type => 4 }, # our stackpointer
{ name => "o7", realname => "r15", type => 1 }, # temp. value / address of CALL instr. { name => "o7", realname => "o6", type => 1 }, # temp. value / address of CALL instr.
# window's local registers # window's local registers
{ name => "l0", realname => "r16", type => 2 }, { name => "l0", realname => "l0", type => 2 },
{ name => "l1", realname => "r17", type => 2 }, { name => "l1", realname => "l1", type => 2 },
{ name => "l2", realname => "r18", type => 2 }, { name => "l2", realname => "l2", type => 2 },
{ name => "l3", realname => "r19", type => 2 }, { name => "l3", realname => "l3", type => 2 },
{ name => "l4", realname => "r20", type => 2 }, { name => "l4", realname => "l4", type => 2 },
{ name => "l5", realname => "r21", type => 2 }, { name => "l5", realname => "l5", type => 2 },
{ name => "l6", realname => "r22", type => 2 }, { name => "l6", realname => "l6", type => 2 },
{ name => "l7", realname => "r23", type => 2 }, { name => "l7", realname => "l7", type => 2 },
# window's in registers # window's in registers
{ name => "i0", realname => "r24", type => 2 }, # incoming param1 / return value to caller { name => "i0", realname => "i0", type => 2 }, # incoming param1 / return value to caller
{ name => "i1", realname => "r25", type => 2 }, # param 2 { name => "i1", realname => "i1", type => 2 }, # param 2
{ name => "i2", realname => "r26", type => 2 }, # param 3 { name => "i2", realname => "i2", type => 2 }, # param 3
{ name => "i3", realname => "r27", type => 2 }, # param 4 { name => "i3", realname => "i3", type => 2 }, # param 4
{ name => "i4", realname => "r28", type => 2 }, # param 5 { name => "i4", realname => "i4", type => 2 }, # param 5
{ name => "i5", realname => "r29", type => 2 }, # param 6 { name => "i5", realname => "i5", type => 2 }, # param 6
{ name => "fp", realname => "r30", type => 4 }, # our framepointer { name => "fp", realname => "i6", type => 4 }, # our framepointer
{ name => "i7", realname => "r31", type => 2 }, # return address - 8 { name => "i7", realname => "i7", type => 2 }, # return address - 8
{ mode => $mode_gp } { mode => $mode_gp }
], ],
flags => [ flags => [
...@@ -323,7 +323,6 @@ my %binop_operand_constructors = ( ...@@ -323,7 +323,6 @@ my %binop_operand_constructors = (
# commutative operations # commutative operations
Add => { Add => {
op_flags => "C",
irn_flags => "R", irn_flags => "R",
comment => "construct Add: Add(a, b) = Add(b, a) = a + b", comment => "construct Add: Add(a, b) = Add(b, a) = a + b",
mode => $mode_gp, mode => $mode_gp,
...@@ -354,6 +353,30 @@ Load => { ...@@ -354,6 +353,30 @@ Load => {
emit => '. ld%LM [%S1%O], %D1' emit => '. ld%LM [%S1%O], %D1'
}, },
LoadHi => {
op_flags => "L|F",
comment => "construct LoadHi: Load(ptr, mem) = sethi hi(ptr) -> reg",
state => "exc_pinned",
ins => [ "ptr", "mem" ],
outs => [ "res", "M" ],
reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
attr_type => "sparc_load_store_attr_t",
attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
emit => '