#!/usr/bin/perl -w
#
-# Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
+# Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
#
# This file is part of libFirm.
#
my @types;
if ($t & 1) {
- push(@types, "arch_register_type_caller_save");
- }
-
- if ($t & 2) {
- push(@types, "arch_register_type_callee_save");
- }
-
- if ($t & 4) {
push(@types, "arch_register_type_ignore");
}
- if ($t & 8) {
+ if ($t & 2) {
push(@types, "arch_register_type_joker");
}
- if ($t & 16) {
+ if ($t & 4) {
push(@types, "arch_register_type_virtual");
}
- if ($t & 32) {
+ if ($t & 8) {
push(@types, "arch_register_type_state");
}
}
# stacks for output
-my @obst_regtypes_def; # stack for the register type variables definitions
-my @obst_regtypes_decl;# stack for the register type variables declarations
-my @obst_regclasses; # stack for the register class variables
-my @obst_classdef; # stack to define a name for a class index
-my @obst_regdef; # stack to define a name for a register index
-my @obst_reginit; # stack for the register type inits
-my @obst_req; # stack for the register requirements
-my @obst_limit_func; # stack for functions to return a subset of a register class
-my @obst_header_all; # stack for some extern struct defs needed for bearch_$arch include
-
-my $numregs;
+my $regtypes_def; # stack for the register type variables definitions
+my $regtypes_decl;# stack for the register type variables declarations
+my @regclasses; # stack for the register class variables
+my $classdef; # stack to define a name for a class index
+my $regdef; # stack to define a name for a register index
+my $regdef2;
+my $regcounts;
+my $reginit; # stack for the register type inits
+my $single_constraints_decls;
+my $single_constraints;
+
my $class_ptr;
my $class_idx = 0;
-my $tmp;
-
-my %reg2class;
-my %regclass2len;
+my %regclass2len = ();
+my %reg2class = ();
-push(@obst_classdef, "enum reg_classes {\n");
+$classdef .= "enum reg_classes {\n";
my $class_mode;
+foreach my $class_name (keys(%reg_classes)) {
+ my @class = @{ $reg_classes{"$class_name"} };
+
+ my $idx = 0;
+ foreach (@class) {
+ if (defined($_->{name})) {
+ $reg2class{$_->{name}} = {
+ "class" => $class_name,
+ "index" => $idx
+ };
+ }
+ $idx++;
+ }
+ $regclass2len{$class_name} = $idx;
+}
+
+sub get_limited_array {
+ my $reg = shift;
+ my $regclass = $reg2class{"$reg"}{"class"};
+ my $ucname = uc($reg);
+ my $result = "{ ";
+
+ my $limitedbitsetlen = $regclass2len{$regclass};
+ my $arraylen = ($limitedbitsetlen+31) / 32;
+ my $firstreg = uc($reg_classes{$regclass}[0]->{"name"});
+ my $classuc = uc($regclass);
+ my $first = 1;
+ for (my $i = 0; $i < $arraylen; ++$i) {
+ if ($first) {
+ $first = 0;
+ } else {
+ $result .= ", ";
+ }
+
+ my $index = $reg2class{"$reg"}{"index"};
+ if ($index >= $i*32 && $index < ($i+1)*32) {
+ if ($i > 0) {
+ $result .= "(1 << (REG_${classuc}_${ucname} % 32))";
+ } else {
+ $result .= "(1 << REG_${classuc}_${ucname})";
+ }
+ } else {
+ $result .= "0";
+ }
+ }
+ $result .= " }";
+}
+
# generate register type and class variable, init function and default requirements
foreach my $class_name (keys(%reg_classes)) {
my @class = @{ $reg_classes{"$class_name"} };
my $old_classname = $class_name;
$class_name = $arch."_".$class_name;
- $numregs = "N_".$class_name."_REGS";
$class_ptr = "&".$arch."_reg_classes[CLASS_".$class_name."]";
my $flags = pop(@class);
$class_mode = $flags->{"mode"};
$flags_prepared .= "arch_register_class_flag_$flag";
}
} else {
- $flags_prepared = "0";
+ $flags_prepared = "arch_register_class_flag_none";
}
- push(@obst_regtypes_decl, "extern const arch_register_t ${class_name}_regs[$numregs];\n");
+ $single_constraints .= <<EOF;
+static const arch_register_req_t ${arch}_class_reg_req_${old_classname} = {
+ arch_register_req_type_normal,
+ &${arch}_reg_classes[CLASS_${arch}_${old_classname}],
+ NULL,
+ 0,
+ 0,
+ 1
+};
+EOF
- push(@obst_classdef, "\tCLASS_$class_name = $class_idx,\n");
- push(@obst_regclasses, "{ \"$class_name\", $numregs, NULL, ".$class_name."_regs, $flags_prepared }");
+ $classdef .= "\tCLASS_$class_name = $class_idx,\n";
+ my $numregs = @class;
+ my $first_reg = "&${arch}_registers[REG_". uc($class[0]->{"name"}) . "]";
+ push(@regclasses, "{ $class_idx, \"$class_name\", $numregs, NULL, $first_reg, $flags_prepared, &${arch}_class_reg_req_${old_classname} }");
my $idx = 0;
- push(@obst_reginit, "\t/* set largest possible mode for '$class_name' */\n");
- push(@obst_reginit, "\t$arch\_reg_classes[CLASS_".$class_name."].mode = $class_mode;\n\n");
- push(@obst_regtypes_def, "const arch_register_t ${class_name}_regs[$numregs] = {\n");
-
- push(@obst_regdef, "enum reg_${class_name}_indices {\n");
+ $reginit .= "\t$arch\_reg_classes[CLASS_".$class_name."].mode = $class_mode;\n";
+ my $lastreg;
foreach (@class) {
- my $ucname = uc($_->{"name"});
- my $type = translate_reg_type($_->{"type"});
+ my $name = $_->{"name"};
+ my $ucname = uc($name);
+ 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};
- my $execunitvarname = get_execunit_variable_name($_->{"unit"});
-
-
- $reg2class{$_->{"name"}} = { "class" => $old_classname, "index" => $idx }; # remember reg to class for later use
- push(@obst_regdef, "\tREG_${ucname},\n");
+ my $classuc = uc($old_classname);
+
+ $regdef .= "\tREG_${ucname},\n";
+ $regdef2 .= "\tREG_${classuc}_${ucname} = $idx,\n";
+
+ $regtypes_def .= <<EOF;
+ {
+ "${realname}",
+ ${class_ptr},
+ REG_${classuc}_${ucname},
+ REG_${ucname},
+ ${type},
+ &${arch}_single_reg_req_${old_classname}_${name}
+ },
+EOF
- push(@obst_regtypes_def, "\t{\n");
- push(@obst_regtypes_def, "\t\t\"$realname\",\n");
- push(@obst_regtypes_def, "\t\t$class_ptr,\n");
- push(@obst_regtypes_def, "\t\tREG_${ucname},\n");
- push(@obst_regtypes_def, "\t\t$type,\n");
- push(@obst_regtypes_def, "\t\t$execunitvarname\n");
- push(@obst_regtypes_def, "\t},\n");
+ my $limitedarray = get_limited_array($name);
+ $single_constraints .= <<EOF;
+static const unsigned ${arch}_limited_${old_classname}_${name} [] = ${limitedarray};
+static const arch_register_req_t ${arch}_single_reg_req_${old_classname}_${name} = {
+ arch_register_req_type_limited,
+ ${class_ptr},
+ ${arch}_limited_${old_classname}_${name},
+ 0,
+ 0,
+ 1
+};
+EOF
+ $lastreg = $ucname;
$idx++;
}
- push(@obst_regtypes_def, "};\n");
-
- $regclass2len{$old_classname} = $idx;
- push(@obst_regdef, "\t$numregs = $idx\n");
- push(@obst_regdef, "};\n\n");
+ $regcounts .= "\tN_${class_name}_REGS = $numregs,\n";
$class_idx++;
}
-push(@obst_classdef, "\tN_CLASSES = ".scalar(keys(%reg_classes))."\n");
-push(@obst_classdef, "};\n\n");
+my $archuc = uc($arch);
-$tmp = uc($arch);
+$classdef .= "\tN_${archuc}_CLASSES = ".scalar(keys(%reg_classes))."\n";
+$classdef .= "};\n\n";
# generate header (external usage) file
open(OUT, ">$target_h") || die("Fatal error: Could not open $target_h, reason: $!\n");
* created by: $0 $specfile $target_dir
* \@date $creation_time
*/
-#ifndef FIRM_BE_${tmp}_GEN_${tmp}_REGALLOC_IF_H
-#define FIRM_BE_${tmp}_GEN_${tmp}_REGALLOC_IF_H
+#ifndef FIRM_BE_${archuc}_GEN_${archuc}_REGALLOC_IF_H
+#define FIRM_BE_${archuc}_GEN_${archuc}_REGALLOC_IF_H
#include "../bearch.h"
#include "${arch}_nodes_attr.h"
-EOF
-
-print OUT @obst_regdef, "\n";
-
-print OUT @obst_classdef, "\n";
+/** global register indices for ${arch} registers */
+enum reg_indices {
+${regdef}
+ N_${archuc}_REGISTERS
+};
+/** local register indices for ${arch} registers */
+enum {
+${regdef2}
+};
-print OUT @obst_regtypes_decl, "\n";
+/** number of registers in ${arch} register classes. */
+enum {
+${regcounts}
+};
+${classdef}
-print OUT "extern arch_register_class_t $arch\_reg_classes[N_CLASSES];\n\n";
+extern const arch_register_t ${arch}_registers[N_${archuc}_REGISTERS];
-print OUT "void ".$arch."_register_init(void);\n\n";
+extern arch_register_class_t ${arch}_reg_classes[N_${archuc}_CLASSES];
-print OUT @obst_header_all, "\n";
-
-print OUT "\n#endif\n";
+void ${arch}_register_init(void);
+#endif
+EOF
close(OUT);
-
# generate c file
open(OUT, ">$target_c") || die("Fatal error: Could not open $target_c, reason: $!\n");
* created by: $0 $specfile $target_dir
* \$date $creation_time
*/
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
#include "gen_${arch}_regalloc_if.h"
#include "gen_${arch}_machine.h"
#include "bearch_${arch}_t.h"
-#include "${arch}_map_regs.h"
#include "irmode.h"
+${single_constraints}
EOF
-print OUT "arch_register_class_t ${arch}_reg_classes[] = {\n\t".join(",\n\t", @obst_regclasses)."\n};\n\n";
-
-print OUT @obst_regtypes_def, "\n";
+print OUT "arch_register_class_t ${arch}_reg_classes[] = {\n\t".join(",\n\t", @regclasses)."\n};\n\n";
-print OUT "void ${arch}_register_init(void) {\n";
-print OUT @obst_reginit;
-print OUT "}\n\n";
-
-print OUT @obst_limit_func;
+print OUT<<EOF;
-print OUT @obst_req;
+/** The array of all registers in the ${arch} architecture, sorted by its global index.*/
+const arch_register_t ${arch}_registers[] = {
+${regtypes_def}
+};
+/**
+ * Initializes ${arch} register classes.
+ */
+void ${arch}_register_init(void)
+{
+${reginit}
+}
+EOF
close(OUT);
###