# This script generates C code which creates ands sets up functions and
# data structures for the register allocator.
# Creation: 2005/11/14
-# $Id$
use strict;
use Data::Dumper;
my $target_h = $target_dir."/gen_".$arch."_regalloc_if.h";
# helper function
-sub translate_reg_type {
- my $t = shift;
-
- if ($t == 0) {
- return "arch_register_type_none";
- }
- else {
- 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) {
- push(@types, "arch_register_type_joker");
- }
-
- if ($t & 16) {
- push(@types, "arch_register_type_virtual");
- }
-
- if ($t & 32) {
- push(@types, "arch_register_type_state");
- }
-
- return join(" | ", @types);
- }
+sub map_flags {
+ my $prefix = shift;
+ my $flags = shift || "none";
+ return join(" | ", map { "$prefix$_" } split(/\s*\|\s*/, $flags));
}
# stacks for output
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 $numregs;
my $class_ptr;
my $class_idx = 0;
-my $tmp;
-
my %regclass2len = ();
my %reg2class = ();
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) {
my $index = $reg2class{"$reg"}{"index"};
if ($index >= $i*32 && $index < ($i+1)*32) {
if ($i > 0) {
- $result .= "(1 << (REG_${ucname} % 32))";
+ $result .= "(1 << (REG_${classuc}_${ucname} % 32))";
} else {
- $result .= "(1 << REG_${ucname})";
+ $result .= "(1 << REG_${classuc}_${ucname})";
}
} else {
$result .= "0";
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"};
- my $class_flags = $flags->{"flags"};
- my $flags_prepared = "";
-
- if(defined($class_flags)) {
- my $first = 1;
- foreach my $flag (split(/\|/, $class_flags)) {
- if(!$first) {
- $flags_prepared .= "|";
- } else {
- $first = 0;
- }
- $flags_prepared .= "arch_register_class_flag_$flag";
- }
- } else {
- $flags_prepared = "0";
- }
-
- $single_constraints_decls .= <<EOF;
-static const arch_register_req_t ${arch}_class_reg_req_${old_classname};
-EOF
+ my $flags_prepared = map_flags("arch_register_class_flag_", $flags->{"flags"});
$single_constraints .= <<EOF;
static const arch_register_req_t ${arch}_class_reg_req_${old_classname} = {
};
EOF
- $regtypes_decl .= "extern const arch_register_t ${class_name}_regs[$numregs];\n";
-
$classdef .= "\tCLASS_$class_name = $class_idx,\n";
- push(@regclasses, "{ $class_idx, \"$class_name\", $numregs, NULL, ".$class_name."_regs, $flags_prepared, &${arch}_class_reg_req_${old_classname} }");
+ 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;
$reginit .= "\t$arch\_reg_classes[CLASS_".$class_name."].mode = $class_mode;\n";
- $regtypes_def .= "const arch_register_t ${class_name}_regs[$numregs] = {\n";
-
- $regdef .= "enum reg_${class_name}_indices {\n";
+ my $lastreg;
foreach (@class) {
- my $name = $_->{"name"};
+ my $name = $_->{"name"};
my $ucname = uc($name);
- my $type = translate_reg_type($_->{"type"});
+ my $type = map_flags("arch_register_type_", $_->{"type"});
# realname is name if not set by user
$_->{"realname"} = $_->{"name"} if (! exists($_->{"realname"}));
my $realname = $_->{realname};
+ my $classuc = uc($old_classname);
- $regdef .= "\tREG_${ucname},\n";
+ $regdef .= "\tREG_${ucname},\n";
+ $regdef2 .= "\tREG_${classuc}_${ucname} = $idx,\n";
+ my $dwarf_number = 0;
+ if (defined($_->{dwarf})) {
+ $dwarf_number = $_->{dwarf};
+ }
$regtypes_def .= <<EOF;
{
"${realname}",
${class_ptr},
+ REG_${classuc}_${ucname},
REG_${ucname},
${type},
- &${arch}_single_reg_req_${old_classname}_${name}
+ &${arch}_single_reg_req_${old_classname}_${name},
+ ${dwarf_number}
},
EOF
};
EOF
+ $lastreg = $ucname;
$idx++;
}
- $regtypes_def .= "};\n";
-
- $regdef .= "\t$numregs = $idx\n";
- $regdef .= "};\n\n";
+ $regcounts .= "\tN_${class_name}_REGS = $numregs,\n";
$class_idx++;
}
-$classdef .= "\tN_CLASSES = ".scalar(keys(%reg_classes))."\n";
-$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 "bearch.h"
#include "${arch}_nodes_attr.h"
+/** global register indices for ${arch} registers */
+enum reg_indices {
${regdef}
+ N_${archuc}_REGISTERS
+};
+/** local register indices for ${arch} registers */
+enum {
+${regdef2}
+};
+
+/** number of registers in ${arch} register classes. */
+enum {
+${regcounts}
+};
${classdef}
-${regtypes_decl}
-extern arch_register_class_t ${arch}_reg_classes[N_CLASSES];
+extern const arch_register_t ${arch}_registers[N_${archuc}_REGISTERS];
+
+extern arch_register_class_t ${arch}_reg_classes[N_${archuc}_CLASSES];
void ${arch}_register_init(void);
-unsigned ${arch}_get_n_regs(void);
#endif
EOF
#include "config.h"
#include "gen_${arch}_regalloc_if.h"
-#include "gen_${arch}_machine.h"
#include "bearch_${arch}_t.h"
#include "irmode.h"
-${single_constraints_decls}
+${single_constraints}
EOF
print OUT "arch_register_class_t ${arch}_reg_classes[] = {\n\t".join(",\n\t", @regclasses)."\n};\n\n";
print OUT<<EOF;
-${single_constraints}
+
+/** 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);
-
-###
-# Gets the variable name for the execution unit assigned to this register.
-###
-sub get_execunit_variable_name {
- my $unit = shift;
- my $name = "NULL";
- my $uc_arch = uc($arch);
-
- if ($unit) {
- my $found = 0;
-SRCH: foreach my $cur_type (keys(%cpu)) {
- foreach my $cur_unit (@{ $cpu{"$cur_type"} }) {
- if ($unit eq $cur_unit) {
- my $tp_name = "$arch\_execution_units_$cur_type";
- my $unit_name = "$uc_arch\_EXECUNIT_TP_$cur_type\_$unit";
- $name = "&".$tp_name."[".$unit_name."]";
- $found = 1;
- last SRCH;
- }
- }
- }
-
- if (! $found) {
- print STDERR "Invalid execution unit $unit specified!\n";
- }
- }
-
- return $name;
-}