sparc: implement float->unsigned conversions
[libfirm] / ir / be / scripts / generate_regalloc_if.pl
index 9c2cb6f..981c4f2 100755 (executable)
@@ -22,7 +22,6 @@
 # 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;
@@ -61,26 +60,18 @@ sub translate_reg_type {
                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");
                }
 
@@ -94,16 +85,15 @@ 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 $numregs;
 my $class_ptr;
 my $class_idx = 0;
 
-my $tmp;
-
 my %regclass2len = ();
 my %reg2class = ();
 
@@ -135,6 +125,8 @@ sub get_limited_array {
 
        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) {
@@ -146,9 +138,9 @@ sub get_limited_array {
                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";
@@ -163,7 +155,6 @@ foreach my $class_name (keys(%reg_classes)) {
        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"};
@@ -181,47 +172,46 @@ foreach my $class_name (keys(%reg_classes)) {
                        $flags_prepared .= "arch_register_class_flag_$flag";
                }
        } else {
-               $flags_prepared = "0";
+               $flags_prepared = "arch_register_class_flag_none";
        }
 
-       $single_constraints_decls .= <<EOF;
-static const arch_register_req_t ${arch}_class_reg_req_${old_classname};
-EOF
-
        $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
+       0,
+       1
 };
 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   = "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 $classuc = uc($old_classname);
 
-               $regdef .= "\tREG_${ucname},\n";
+               $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}
@@ -236,24 +226,23 @@ static const arch_register_req_t ${arch}_single_reg_req_${old_classname}_${name}
        ${class_ptr},
        ${arch}_limited_${old_classname}_${name},
        0,
-       0
+       0,
+       1
 };
 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");
@@ -269,20 +258,33 @@ print OUT<<EOF;
  *         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
@@ -308,52 +310,27 @@ print OUT<<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;
-}