Commit 8a1c0ad6 authored by Matthias Braun's avatar Matthias Braun
Browse files

make sparc+arm backend completely independent from beabi

[r28073]
parent b4647d67
......@@ -12,48 +12,40 @@ $mode_gp = "mode_Iu";
$mode_flags = "mode_Bu";
$mode_fp = "mode_E";
# register types:
$normal = 0; # no special type
$caller_save = 1; # caller save (register must be saved by the caller of a function)
$callee_save = 2; # callee save (register must be saved by the called function)
$ignore = 4; # ignore (do not assign this register)
$arbitrary = 8; # emitter can choose an arbitrary register of this class
$virtual = 16; # the register is a virtual one
$state = 32; # register represents a state
# NOTE: Last entry of each class is the largest Firm-Mode a register can hold
%reg_classes = (
gp => [
{ name => "r0", type => $caller_save },
{ name => "r1", type => $caller_save },
{ name => "r2", type => $caller_save },
{ name => "r3", type => $caller_save },
{ name => "r4", type => $callee_save },
{ name => "r5", type => $callee_save },
{ name => "r6", type => $callee_save },
{ name => "r7", type => $callee_save },
{ name => "r8", type => $callee_save },
{ name => "r9", type => $callee_save },
{ name => "r10", type => $callee_save },
{ name => "r11", type => $callee_save },
{ name => "r12", type => $ignore }, # reserved for linker/immediate fixups
{ name => "sp", type => $ignore }, # this is our stack pointer
{ name => "lr", type => $callee_save | $caller_save }, # this is our return address
{ name => "pc", type => $ignore }, # this is our program counter
{ name => "r0" },
{ name => "r1" },
{ name => "r2" },
{ name => "r3" },
{ name => "r4" },
{ name => "r5" },
{ name => "r6" },
{ name => "r7" },
{ name => "r8" },
{ name => "r9" },
{ name => "r10" },
{ name => "r11" },
{ name => "r12" },
{ name => "sp" },
{ name => "lr" },
{ name => "pc" },
{ mode => $mode_gp }
],
fpa => [
{ name => "f0", type => $caller_save },
{ name => "f1", type => $caller_save },
{ name => "f2", type => $caller_save },
{ name => "f3", type => $caller_save },
{ name => "f4", type => $caller_save },
{ name => "f5", type => $caller_save },
{ name => "f6", type => $caller_save },
{ name => "f7", type => $caller_save },
{ name => "f0" },
{ name => "f1" },
{ name => "f2" },
{ name => "f3" },
{ name => "f4" },
{ name => "f5" },
{ name => "f6" },
{ name => "f7" },
{ mode => $mode_fp }
],
flags => [
{ name => "fl", type => 0 },
{ name => "fl" },
{ mode => $mode_flags, flags => "manual_ra" }
],
);
......@@ -426,7 +418,8 @@ SwitchJmp => {
mode => "mode_T",
attr => "int n_projs, long def_proj_num",
init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n".
"\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);",
"\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);\n".
"\tinfo->out_infos = NULL;",
reg_req => { in => [ "gp" ], out => [ "none" ] },
attr_type => "arm_SwitchJmp_attr_t",
},
......
......@@ -342,7 +342,6 @@ static ir_node *handle_constraints(be_chordal_alloc_env_t *alloc_env,
assert(assignment[i] >= 0 && "there must have been a register assigned (node not register pressure faithful?)");
reg = arch_register_for_index(env->cls, assignment[i]);
assert(! (reg->type & arch_register_type_ignore));
irn = alloc_nodes[i];
if (irn != NULL) {
......@@ -502,7 +501,6 @@ static void assign(ir_node *block, void *env_ptr)
col = get_next_free_reg(alloc_env, colors);
reg = arch_register_for_index(env->cls, col);
assert(arch_get_irn_register(irn) == NULL && "This node must not have been assigned a register yet");
assert(!arch_register_type_is(reg, ignore) && "Must not assign ignore register");
}
bitset_set(colors, col);
......@@ -520,11 +518,6 @@ static void assign(ir_node *block, void *env_ptr)
assert(reg && "Register must have been assigned");
col = arch_register_get_index(reg);
#ifndef NDEBUG
if (!arch_register_type_is(reg, ignore)) {
assert(bitset_is_set(live, nr) && "Cannot have a non live use");
}
#endif
bitset_clear(colors, col);
bitset_clear(live, nr);
......
......@@ -228,15 +228,10 @@ void free_copy_opt(copy_opt_t *co)
static int co_is_optimizable_root(ir_node *irn)
{
const arch_register_req_t *req;
const arch_register_t *reg;
if (arch_irn_is_ignore(irn))
return 0;
reg = arch_get_irn_register(irn);
if (arch_register_type_is(reg, ignore))
return 0;
if (is_Reg_Phi(irn) || is_Perm_Proj(irn))
return 1;
......@@ -805,7 +800,6 @@ static void build_graph_walker(ir_node *irn, void *env)
const arch_register_req_t *req;
copy_opt_t *co = env;
int pos, max;
const arch_register_t *reg;
if (get_irn_mode(irn) == mode_T)
return;
......@@ -813,10 +807,6 @@ static void build_graph_walker(ir_node *irn, void *env)
if (req->cls != co->cls || arch_irn_is_ignore(irn))
return;
reg = arch_get_irn_register(irn);
if (arch_register_type_is(reg, ignore))
return;
if (is_Reg_Phi(irn)) { /* Phis */
for (pos=0, max=get_irn_arity(irn); pos<max; ++pos) {
ir_node *arg = get_irn_n(irn, pos);
......@@ -898,6 +888,8 @@ void co_dump_appel_graph(const copy_opt_t *co, FILE *f)
be_ifg_t *ifg = co->cenv->ifg;
int *color_map = ALLOCAN(int, co->cls->n_regs);
int *node_map = XMALLOCN(int, get_irg_last_idx(co->irg) + 1);
ir_graph *irg = co->irg;
be_irg_t *birg = be_birg_from_irg(irg);
ir_node *irn;
nodes_iter_t it;
......@@ -908,7 +900,11 @@ void co_dump_appel_graph(const copy_opt_t *co, FILE *f)
n_regs = 0;
for (i = 0; i < co->cls->n_regs; ++i) {
const arch_register_t *reg = &co->cls->regs[i];
color_map[i] = arch_register_type_is(reg, ignore) ? -1 : n_regs++;
if (rbitset_is_set(birg->allocatable_regs, reg->global_index)) {
color_map[i] = n_regs++;
} else {
color_map[i] = -1;
}
}
/*
......
......@@ -243,6 +243,7 @@ static void print_regclasses(void)
}
end_list("registers");
#if 0
begin_block_mapping("flags");
for (r = 0; r < n_regs; ++r) {
const arch_register_t *reg = arch_register_for_index(cls, r);
......@@ -255,6 +256,7 @@ static void print_regclasses(void)
}
}
end_block_mapping("flags");
#endif
end_block_mapping(NULL);
}
......
......@@ -874,10 +874,12 @@ void be_set_constr_single_reg_in(ir_node *node, int pos,
void be_set_constr_single_reg_out(ir_node *node, int pos,
const arch_register_t *reg, arch_register_req_type_t additional_types)
{
ir_graph *irg = get_irn_irg(node);
be_irg_t *birg = be_birg_from_irg(irg);
const arch_register_req_t *req;
/* if we have an ignore register, add ignore flag and just assign it */
if (reg->type & arch_register_type_ignore) {
if (!rbitset_is_set(birg->allocatable_regs, reg->global_index)) {
additional_types |= arch_register_req_type_ignore;
}
......
......@@ -59,6 +59,7 @@ static void prepare_constr_insn(be_pre_spill_env_t *env, ir_node *node)
const arch_register_class_t *cls = env->cls;
ir_node *block = get_nodes_block(node);
const ir_graph *irg = env->irg;
be_irg_t *birg = be_birg_from_irg(irg);
be_lv_t *lv = be_get_irg_liveness(irg);
unsigned *tmp = NULL;
unsigned *def_constr = NULL;
......@@ -70,15 +71,14 @@ static void prepare_constr_insn(be_pre_spill_env_t *env, ir_node *node)
* fullfil the constraint
* (typical example: stack pointer as input to copyb)
* TODO: This really just checks precolored registers at the moment and
* ignore the general case of not matching in/out constraints
* ignores the general case of not matching in/out constraints
*/
for (i = 0; i < arity; ++i) {
ir_node *op = get_irn_n(node, i);
ir_node *copy;
const arch_register_t *reg;
const arch_register_req_t *req;
ir_node *op = get_irn_n(node, i);
const arch_register_req_t *req = arch_get_register_req(node, i);
const arch_register_t *reg;
ir_node *copy;
req = arch_get_register_req(node, i);
if (req->cls != cls)
continue;
reg = arch_get_irn_register(op);
......@@ -88,7 +88,7 @@ static void prepare_constr_insn(be_pre_spill_env_t *env, ir_node *node)
/* precolored with an ignore register (which is not a joker like
unknown/noreg) */
if (arch_register_type_is(reg, joker)
|| !arch_register_type_is(reg, ignore))
|| rbitset_is_set(birg->allocatable_regs, reg->global_index))
continue;
if (! (req->type & arch_register_req_type_limited))
......@@ -100,7 +100,8 @@ static void prepare_constr_insn(be_pre_spill_env_t *env, ir_node *node)
stat_ev_int("constr_copy", 1);
sched_add_before(node, copy);
set_irn_n(node, i, copy);
DBG((dbg, LEVEL_3, "inserting ignore arg copy %+F for %+F pos %d\n", copy, node, i));
DBG((dbg, LEVEL_3, "inserting ignore arg copy %+F for %+F pos %d\n",
copy, node, i));
}
/* insert copies for nodes that occur constrained more than once. */
......
......@@ -305,6 +305,7 @@ void be_abi_fix_stack_nodes(ir_graph *irg)
const arch_env_t *arch_env = be_get_irg_arch_env(irg);
be_irg_t *birg = be_birg_from_irg(irg);
const arch_register_req_t *sp_req = birg->sp_req;
const arch_register_t *sp = arch_env->sp;
be_ssa_construction_env_t senv;
int i, len;
ir_node **phis;
......@@ -322,9 +323,10 @@ void be_abi_fix_stack_nodes(ir_graph *irg)
new_sp_req->width = 1;
limited_bitset = rbitset_obstack_alloc(obst, new_sp_req->cls->n_regs);
rbitset_set(limited_bitset, arch_register_get_index(arch_env->sp));
rbitset_set(limited_bitset, arch_register_get_index(sp));
new_sp_req->limited = limited_bitset;
if (arch_env->sp->type & arch_register_type_ignore) {
if (!rbitset_is_set(birg->allocatable_regs, sp->global_index)) {
new_sp_req->type |= arch_register_req_type_ignore;
}
......
......@@ -819,13 +819,14 @@ static void peephole_Load_IncSP_to_pop(ir_node *irn)
/**
* Find a free GP register if possible, else return NULL.
*/
static const arch_register_t *get_free_gp_reg(void)
static const arch_register_t *get_free_gp_reg(ir_graph *irg)
{
be_irg_t *birg = be_birg_from_irg(irg);
int i;
for (i = 0; i < N_ia32_gp_REGS; ++i) {
const arch_register_t *reg = &ia32_reg_classes[CLASS_ia32_gp].regs[i];
if (arch_register_type_is(reg, ignore))
if (!rbitset_is_set(birg->allocatable_regs, reg->global_index))
continue;
if (be_peephole_get_value(CLASS_ia32_gp, i) == NULL)
......@@ -907,7 +908,7 @@ static void peephole_be_IncSP(ir_node *node)
if (offset < 0) {
/* we need a free register for pop */
reg = get_free_gp_reg();
reg = get_free_gp_reg(get_irn_irg(node));
if (reg == NULL)
return;
......@@ -1196,7 +1197,7 @@ static void peephole_ia32_Imul_split(ir_node *imul)
return;
}
/* we need a free register */
reg = get_free_gp_reg();
reg = get_free_gp_reg(get_irn_irg(imul));
if (reg == NULL)
return;
......
......@@ -208,9 +208,10 @@ EOF
$reginit .= "\t$arch\_reg_classes[CLASS_".$class_name."].mode = $class_mode;\n";
my $lastreg;
foreach (@class) {
my $name = $_->{"name"};
my $name = $_->{"name"};
my $ucname = uc($name);
my $type = translate_reg_type($_->{"type"});
my $type = "arch_register_type_none";
$type = translate_reg_type($_->{"type"}) if (exists($_->{"type"}));
# realname is name if not set by user
$_->{"realname"} = $_->{"name"} if (! exists($_->{"realname"}));
my $realname = $_->{realname};
......
......@@ -10,103 +10,92 @@ $mode_fp = "mode_F";
$mode_fp2 = "mode_D";
$mode_fp4 = "mode_E"; # not correct, we need to register a new mode
$normal = 0; # no special type
$caller_save = 1; # caller save (register must be saved by the caller of a function)
$callee_save = 2; # callee save (register must be saved by the called function)
$ignore = 4; # ignore (do not assign this register)
$arbitrary = 8; # emitter can choose an arbitrary register of this class
$virtual = 16; # the register is a virtual one
$state = 32; # register represents a state
# available SPARC registers: 8 globals, 24 window regs (8 ins, 8 outs, 8 locals)
%reg_classes = (
gp => [
{ name => "g0", type => $ignore }, # hardwired 0, behaves like /dev/null
{ name => "g1", type => $caller_save }, # temp. value
{ name => "g2", type => $caller_save },
{ name => "g3", type => $caller_save },
{ name => "g4", type => $caller_save },
{ name => "g5", type => $ignore }, # reserved by SPARC ABI
{ name => "g6", type => $ignore }, # reserved by SPARC ABI
{ name => "g7", type => $ignore }, # reserved by SPARC ABI
# window's out registers
{ name => "o0", type => $caller_save }, # param 1 / return value from callee
{ name => "o1", type => $caller_save }, # param 2
{ name => "o2", type => $caller_save }, # param 3
{ name => "o3", type => $caller_save }, # param 4
{ name => "o4", type => $caller_save }, # param 5
{ name => "o5", type => $caller_save }, # param 6
{ name => "sp", type => $ignore }, # our stackpointer
{ name => "o7", type => $ignore }, # temp. value / address of CALL instr.
# window's local registers
{ name => "l0", type => 0 },
{ name => "l1", type => 0 },
{ name => "l2", type => 0 },
{ name => "l3", type => 0 },
{ name => "l4", type => 0 },
{ name => "l5", type => 0 },
{ name => "l6", type => 0 },
{ name => "l7", type => 0 },
# window's in registers
{ name => "i0", type => 0 }, # incoming param1 / return value to caller
{ name => "i1", type => 0 }, # param 2
{ name => "i2", type => 0 }, # param 3
{ name => "i3", type => 0 }, # param 4
{ name => "i4", type => 0 }, # param 5
{ name => "i5", type => 0 }, # param 6
{ name => "frame_pointer", realname => "fp", type => $ignore }, # our framepointer
{ name => "i7", type => $ignore }, # return address - 8
{ name => "g0" },
{ name => "g1" },
{ name => "g2" },
{ name => "g3" },
{ name => "g4" },
{ name => "g5" },
{ name => "g6" },
{ name => "g7" },
{ name => "o0" },
{ name => "o1" },
{ name => "o2" },
{ name => "o3" },
{ name => "o4" },
{ name => "o5" },
{ name => "sp" },
{ name => "o7" },
{ name => "l0" },
{ name => "l1" },
{ name => "l2" },
{ name => "l3" },
{ name => "l4" },
{ name => "l5" },
{ name => "l6" },
{ name => "l7" },
{ name => "i0" },
{ name => "i1" },
{ name => "i2" },
{ name => "i3" },
{ name => "i4" },
{ name => "i5" },
{ name => "frame_pointer", realname => "fp" },
{ name => "i7" },
{ mode => $mode_gp }
],
fpflags_class => [
{ name => "fpflags", type => $ignore },
{ name => "fpflags" },
{ mode => $mode_fpflags, flags => "manual_ra" }
],
flags_class => [
{ name => "flags", type => $ignore },
{ name => "flags" },
{ mode => $mode_flags, flags => "manual_ra" }
],
mul_div_high_res => [
{ name => "y", type => $ignore },
{ name => "y" },
{ mode => $mode_gp, flags => "manual_ra" }
],
# fp registers can be accessed any time
fp => [
{ name => "f0", type => $caller_save },
{ name => "f1", type => $caller_save },
{ name => "f2", type => $caller_save },
{ name => "f3", type => $caller_save },
{ name => "f4", type => $caller_save },
{ name => "f5", type => $caller_save },
{ name => "f6", type => $caller_save },
{ name => "f7", type => $caller_save },
{ name => "f8", type => $caller_save },
{ name => "f9", type => $caller_save },
{ name => "f10", type => $caller_save },
{ name => "f11", type => $caller_save },
{ name => "f12", type => $caller_save },
{ name => "f13", type => $caller_save },
{ name => "f14", type => $caller_save },
{ name => "f15", type => $caller_save },
{ name => "f16", type => $caller_save },
{ name => "f17", type => $caller_save },
{ name => "f18", type => $caller_save },
{ name => "f19", type => $caller_save },
{ name => "f20", type => $caller_save },
{ name => "f21", type => $caller_save },
{ name => "f22", type => $caller_save },
{ name => "f23", type => $caller_save },
{ name => "f24", type => $caller_save },
{ name => "f25", type => $caller_save },
{ name => "f26", type => $caller_save },
{ name => "f27", type => $caller_save },
{ name => "f28", type => $caller_save },
{ name => "f29", type => $caller_save },
{ name => "f30", type => $caller_save },
{ name => "f31", type => $caller_save },
{ name => "f0" },
{ name => "f1" },
{ name => "f2" },
{ name => "f3" },
{ name => "f4" },
{ name => "f5" },
{ name => "f6" },
{ name => "f7" },
{ name => "f8" },
{ name => "f9" },
{ name => "f10" },
{ name => "f11" },
{ name => "f12" },
{ name => "f13" },
{ name => "f14" },
{ name => "f15" },
{ name => "f16" },
{ name => "f17" },
{ name => "f18" },
{ name => "f19" },
{ name => "f20" },
{ name => "f21" },
{ name => "f22" },
{ name => "f23" },
{ name => "f24" },
{ name => "f25" },
{ name => "f26" },
{ name => "f27" },
{ name => "f28" },
{ name => "f29" },
{ name => "f30" },
{ name => "f31" },
{ mode => $mode_fp }
]
); # %reg_classes
......
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