fixed a lot of bugs
authorChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Tue, 13 Dec 2005 15:41:00 +0000 (15:41 +0000)
committerChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Tue, 13 Dec 2005 15:41:00 +0000 (15:41 +0000)
ir/be/scripts/generate_emitter.pl
ir/be/scripts/generate_new_opcodes.pl
ir/be/scripts/generate_regalloc_if.pl

index 98beec1..d9966ea 100755 (executable)
@@ -42,47 +42,95 @@ foreach my $op (keys(%nodes)) {
   # skip this node description if no emit information is available
   next if (!$n{"emit"} || length($n{"emit"}) < 1);
 
-  $line = "void emit_".$arch."_".$op."(FILE *F, ir_node *n)";
+  $line = "void emit_".$arch."_".$op."(ir_node *n, emit_env_t *env)";
   push(@obst_header, $line.";\n");
-  push(@obst_func, $line." {\n");
+  push(@obst_func, $line." {\n  FILE *F = env->out;\n");
 
+  my $cio = 0;
   # check in/out register if needed
   if (exists($n{"check_inout"}) && $n{"check_inout"} == 1) {
     push(@obst_func, "  equalize_dest_src(F, n);\n\n");
+    $cio = 1;
   }
 
   my @emit = split(/\n/, $n{"emit"});
 
-  foreach(@emit) {
+  foreach my $template (@emit) {
     # substitute only lines, starting with a '.'
-    if (/^(\d*)\.\s*/) {
+    if ($template =~ /^(\d*)\.\s*/) {
       my @params;
-      my $regkind;
+      my $res    = "";
+      my $res2   = "";
       my $indent = "  "; # default indent is 2 spaces
 
       $indent = " " x $1 if ($1 && $1 > 0);
       # remove indent, dot and trailing spaces
-      s/^\d*\.\s*//;
+      $template =~ s/^\d*\.\s*//;
       # substitute all format parameter
-      while (/%(([sd])(\d)|([co]))/) {
+      while ($template =~ /\%(([asd])(\d)|([com]))/) {
+        $res  .= $`;      # get everything before the match
+        $res2 .= $`;
+
         if ($4 && $4 eq "c") {
-          push(@params, "node_const_to_str(n)");
+          push(@params, "n");
+          $res  .= "\%c";
+          $res2 .= "\%c";
         }
         elsif ($4 && $4 eq "o") {
-          push(@params, "node_offset_to_str(n)");
+          push(@params, "n");
+          $res  .= "\%o";
+          $res2 .= "\%o";
+        }
+        elsif ($4 && $4 eq "m") {
+          push(@params, "n");
+          $res  .= "\%m";
+          $res2 .= "\%m";
+        }
+        elsif ($2 && $2 eq "s") {
+          push(@params, "n");
+          if ($cio && $3 == 2) {
+            # check_in_out was set: if (s1 != d1) we
+            # need to exchange s2 by s1
+            $res2 .= "%1s"; # get name for first register
+          }
+          else {
+            $res2 .= "%".$3."s"; # substitute %sx with %xs
+          }
+          $res .= "%".$3."s"; # substitute %sx with %xs
         }
-        else {
-          $regkind = ($2 eq "s" ? "source" : "dest");
-          push(@params, "get_".$regkind."_reg_name(n, $3)");
+        elsif ($2 && $2 eq "d") {
+          push(@params, "n");
+          $res  .= "%".$3."d"; # substitute %sx with %xs
+          $res2 .= "%".$3."d"; # substitute %sx with %xs
         }
-        s/%$1/%%\%s/;
+        elsif ($2 && $2 eq "a") {
+          push(@params, "get_irn_n(n, ".($3 - 1).")");
+          $res  .= "%+F";
+          $res2 .= "%+F";
+        }
+
+        $template = $'; # scan everything after the match
       }
+      $res  .= $template; # get the remaining string
+      $res2 .= $template; # get the remaining string
+
       my $parm = "";
       $parm = ", ".join(", ", @params) if (@params);
-      push(@obst_func, $indent.'fprintf(F, "\t'.$_.'\n"'.$parm.');'."\n");
+
+      if ($cio) {
+        push(@obst_func, $indent."if (get_irn_arity(n) > 1 && get_$arch\_in_regnr(n, 1) == get_$arch\_out_regnr(n, 0)) {\n");
+        push(@obst_func, $indent.'  lc_efprintf(ia32_get_arg_env(), F, "\t'.$res2.'\n"'.$parm.');'."\n");
+        push(@obst_func, $indent."}\n");
+        push(@obst_func, $indent."else {\n");
+        push(@obst_func, $indent.'  lc_efprintf(ia32_get_arg_env(), F, "\t'.$res.'\n"'.$parm.');'."\n");
+        push(@obst_func, $indent."}\n");
+      }
+      else {
+        push(@obst_func, $indent.'lc_efprintf(ia32_get_arg_env(), F, "\t'.$res.'\n"'.$parm.');'."\n");
+      }
     }
     else {
-      push(@obst_func, $_,"\n");
+      push(@obst_func, $template,"\n");
     }
   }
   push(@obst_func, "}\n\n");
@@ -107,6 +155,7 @@ print OUT<<EOF;
  */
 
 #include "irnode.h"
+#include "$arch\_emitter.h"
 
 EOF
 
@@ -133,7 +182,6 @@ print OUT<<EOF;
 
 #include "irnode.h"
 #include "gen_$arch\_emitter.h"
-#include "$arch\_emitter.h"
 #include "$arch\_new_nodes.h"
 
 EOF
index c522910..258ee52 100755 (executable)
@@ -31,7 +31,7 @@ unless ($return = do $specfile) {
 use strict "subs";
 
 my $target_c = $target_dir."/gen_".$arch."_new_nodes.c.inl";
-my $target_h = $target_dir."/gen_".$arch."_new_nodes.h.inl";
+my $target_h = $target_dir."/gen_".$arch."_new_nodes.h";
 
 #print Dumper(%nodes);
 
@@ -43,8 +43,10 @@ my @obst_constructor; # stack for node constructor functions
 my @obst_new_irop;    # stack for the new_ir_op calls
 my @obst_header;      # stack for function prototypes
 my @obst_is_archirn;  # stack for the is_$arch_irn() function
+my @obst_cmp_attr;    # stack for the compare attribute functions
 my $orig_op;
 my $arity;
+my $cmp_attr_func;
 
 push(@obst_header, "void ".$arch."_create_opcodes(void);\n");
 
@@ -63,10 +65,23 @@ foreach my $op (keys(%nodes)) {
 
   push(@obst_header, "int is_$op(const ir_node *n);\n");
 
-  $n{"comment"} =~ s/^"|"$//g;
+  $n{"comment"} = "construct $op" if(!exists($n{"comment"}));
+  $n{"comment"} =~ s/^"|"$//g;    # remove "
   $n{"comment"} = "/* ".$n{"comment"}." */\n";
   push(@obst_constructor, $n{"comment"});
 
+  $cmp_attr_func = 0;
+  # create compare attribute function if needed
+  if (exists($n{"cmp_attr"})) {
+    push(@obst_cmp_attr, "static int cmp_attr_$op(ir_node *a, ir_node *b) {\n");
+    push(@obst_cmp_attr, "  asmop_attr *attr_a = get_ia32_attr(a);\n");
+    push(@obst_cmp_attr, "  asmop_attr *attr_b = get_ia32_attr(b);\n");
+    push(@obst_cmp_attr, $n{"cmp_attr"});
+    push(@obst_cmp_attr, "}\n\n");
+
+    $cmp_attr_func = 1;
+  }
+
   # create constructor head
   my $complete_args = "";
   my $arg_names     = "";
@@ -115,6 +130,9 @@ foreach my $op (keys(%nodes)) {
       $temp .= "  in[".($i - 1)."] = op".$i.";\n";
     }
     $temp .= "  res = new_ir_node(db, irg, block, op_$op, mode, $arity, ".($arity > 0 ? "in" : "NULL").");\n";
+    $temp .= "  set_ia32_pncode(res, -1);\n";
+    $temp .= "  res = optimize_node(res);\n";
+    $temp .= "  irn_vrfy_irg(res, irg);\n\n";
 
     # set register flags
     $temp .= "  attr = get_ia32_attr(res);\n\n";
@@ -138,18 +156,18 @@ foreach my $op (keys(%nodes)) {
 
       if (@in) {
         $temp .= "\n  /* allocate memory for IN register requirements and assigned registers */\n";
-        $temp .= "  attr->in_req    = malloc(".($#in + 1)." * sizeof(arch_register_req_t *)); /* space for in requirements */\n";
+        $temp .= "  attr->in_req    = calloc(".($#in + 1).", sizeof(arch_register_req_t *));  /* space for in requirements */\n";
         for ($idx = 0; $idx <= $#in; $idx++) {
-          $temp .= "  attr->in_req[$idx] = &".$op."_reg_req_in_".$idx.";\n";
+          $temp .= "  attr->in_req[$idx] = ".$op."_reg_req_in_".$idx.";\n";
         }
       }
 
       if (@out) {
         $temp .= "\n  /* allocate memory for OUT register requirements and assigned registers */\n";
-        $temp .= "  attr->out_req    = malloc(".($#out + 1)." * sizeof(arch_register_req_t *)); /* space for out requirements */\n";
-        $temp .= "  attr->slots      = calloc(sizeof(arch_register_t *), ".($#out + 1).");     /* space for assigned registers */\n";
+        $temp .= "  attr->out_req    = calloc(".($#out + 1).", sizeof(arch_register_req_t *)); /* space for out requirements */\n";
+        $temp .= "  attr->slots      = calloc(".($#out + 1).", sizeof(arch_register_t *));     /* space for assigned registers */\n";
         for ($idx = 0; $idx <= $#out; $idx++) {
-          $temp .= "  attr->out_req[$idx] = &".$op."_reg_req_out_".$idx.";\n";
+          $temp .= "  attr->out_req[$idx] = ".$op."_reg_req_out_".$idx.";\n";
         }
         $temp .= "  attr->n_res      = ".($#out + 1).";\n";
       }
@@ -173,6 +191,13 @@ foreach my $op (keys(%nodes)) {
   $n{"state"}    = "pinned" if (! exists($n{"state"}));
   $n{"op_flags"} = "N"      if (! exists($n{"op_flags"}));
 
+  push(@obst_new_irop, "\n  memset(&ops, 0, sizeof(ops));\n");
+  push(@obst_new_irop, "  ops.dump_node     = dump_node_$arch;\n");
+
+  if ($cmp_attr_func) {
+    push(@obst_new_irop, "  ops.node_cmp_attr = cmp_attr_$op;\n");
+  }
+
   $temp  = "  op_$op = new_ir_op(get_next_ir_opcode(), \"$op\", op_pin_state_".$n{"state"}.", ".$n{"op_flags"};
   $temp .= ", ".translate_arity($arity).", 0, sizeof(asmop_attr), &ops);\n";
   push(@obst_new_irop, $temp);
@@ -182,6 +207,8 @@ foreach my $op (keys(%nodes)) {
 
 open(OUT, ">$target_c") || die("Could not open $target_c, reason: $!\n");
 
+print OUT @obst_cmp_attr;
+print OUT "\n";
 print OUT @obst_opvar;
 print OUT "\n";
 print OUT @obst_get_opvar;
@@ -207,9 +234,6 @@ void $arch\_create_opcodes(void) {
 
   ir_op_ops ops;
 
-  memset(&ops, 0, sizeof(ops));
-  ops.dump_node = dump_node_$arch;
-
 ENDOFMAIN
 
 print OUT @obst_new_irop;
@@ -229,19 +253,24 @@ close(OUT);
 sub translate_arity {
   my $arity = shift;
 
-  if    ($arity == 0) {
-    return "oparity_zero";
-  }
-  elsif ($arity == 1) {
-    return "oparity_unary";
-  }
-  elsif ($arity == 1) {
-    return "oparity_binary";
-  }
-  elsif ($arity == 1) {
-    return "oparity_trinary";
+  if ($arity =~ /^\d+$/) {
+    if    ($arity == 0) {
+      return "oparity_zero";
+    }
+    elsif ($arity == 1) {
+      return "oparity_unary";
+    }
+    elsif ($arity == 2) {
+      return "oparity_binary";
+    }
+    elsif ($arity == 3) {
+      return "oparity_trinary";
+    }
+    else {
+      return "$arity";
+    }
   }
   else {
-    return "$arity";
+    return "oparity_".$arity;
   }
 }
index b4ab2d5..1738415 100755 (executable)
@@ -28,8 +28,9 @@ unless ($return = do $specfile) {
 }
 use strict "subs";
 
-my $target_c = $target_dir."/gen_".$arch."_regalloc_if.c.inl";
-my $target_h = $target_dir."/gen_".$arch."_regalloc_if.h";
+my $target_c   = $target_dir."/gen_".$arch."_regalloc_if.c";
+my $target_h   = $target_dir."/gen_".$arch."_regalloc_if.h";
+my $target_h_t = $target_dir."/gen_".$arch."_regalloc_if_t.h";
 
 # helper function
 my @rt = ("arch_register_type_none",
@@ -41,23 +42,44 @@ my @rt = ("arch_register_type_none",
 # stacks for output
 my @obst_regtypes;     # stack for the register type variables
 my @obst_regclasses;   # stack for the register class variables
-my @obst_classdef;     # stack to assign a number to a certain class
+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_defreq_head;  # stack for prototypes of default requirement function
+my @obst_header_all;   # stack for some extern struct defs needed for bearch_$arch include
 
 my $numregs;
+my $class_ptr;
 my $class_idx = 0;
 
+my $tmp;
+
 my %reg2class;
 
-# generate register type and class variable and init function
+# there is a default NONE requirement
+$tmp = "/* Default NONE register requirements */\n";
+$tmp .= "const arch_register_req_t ia32_default_req_none = {\n";
+$tmp .= "  arch_register_req_type_none,\n";
+$tmp .= "  NULL,\n";
+$tmp .= "  { NULL }\n";
+$tmp .= "};\n\n";
+push(@obst_req, $tmp);
+
+push(@obst_header_all, "extern arch_register_class_t $arch\_reg_classes[N_CLASSES];\n\n");
+push(@obst_header_all, "extern const arch_register_req_t ia32_default_req_none;\n");
+
+push(@obst_classdef, "#define N_CLASSES ".scalar(keys(%reg_classes))."\n");
+
+# 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."]";
 
   push(@obst_regtypes, "#define $numregs ".($#class + 1)."\n");
   push(@obst_regtypes, "arch_register_t ".$class_name."_regs[$numregs];\n\n");
@@ -65,12 +87,54 @@ foreach my $class_name (keys(%reg_classes)) {
   push(@obst_classdef, "#define CLASS_$class_name $class_idx\n");
   push(@obst_regclasses, "{ \"$class_name\", $numregs, ".$class_name."_regs }");
 
+  # there is a default NORMAL requirement for each class
+  $tmp  = "/* Default NORMAL register requirements for class $class_name */\n";
+  $tmp .= "const arch_register_req_t ia32_default_req_$class_name = {\n";
+  $tmp .= "  arch_register_req_type_normal,\n";
+  $tmp .= "  $class_ptr,\n";
+  $tmp .= "  { NULL }\n";
+  $tmp .= "};\n\n";
+  push(@obst_req, $tmp);
+
+  push(@obst_header_all, "\nextern const arch_register_req_t ia32_default_req_$class_name;\n");
+
   my $idx = 0;
   push(@obst_reginit, "  /* Init of all registers in class '$class_name' */\n\n");
   foreach (@class) {
+    # For each class we build for each of it's member registers a limit function
+    # which limits the class to this particular register. We also build the
+    # corresponding requirement structs.
+    # We need those functions to set register requirements on demand in transformation
+    # esp. for Call and RegParams where we can mix int and float parameters.
+
+    my $limit_func_name = $arch."_limit_".$class_name."_".$_->{"name"};
+
+    # push the function prototype
+    $tmp = "int $limit_func_name(const ir_node *irn, int pos, bitset_t *bs)";
+    push(@obst_defreq_head, $tmp.";\n");
+
+    # push the function definition
+    $tmp .= " {\n";
+    $tmp .= "    bs = bitset_clear_all(bs);\n";
+    $tmp .= "    bitset_set(bs, REG_".uc($_->{"name"}).");\n";  # REGISTER to index assignment is done some lines down
+    $tmp .= "    return 1;\n";
+    $tmp .= "}\n\n";
+    push(@obst_limit_func, $tmp);
+
+    # push the default requirement struct
+    $tmp  = "const arch_register_req_t ia32_default_req_$class_name\_".$_->{"name"}." = {\n";
+    $tmp .= "  arch_register_req_type_limited,\n";
+    $tmp .= "  $class_ptr,\n";
+    $tmp .= "  { $limit_func_name }\n";
+    $tmp .= "};\n\n";
+    push(@obst_req, $tmp);
+
+    push(@obst_header_all, "extern const arch_register_req_t ia32_default_req_$class_name\_".$_->{"name"}.";\n");
+
     $reg2class{$_->{"name"}} = { "class" => $old_classname, "index" => $idx }; # remember reg to class for later use
+    push(@obst_regdef, "#define REG_".uc($_->{"name"})." $idx\n");
     push(@obst_reginit, "  ".$class_name."_regs[$idx].name      = \"".$_->{"name"}."\";\n");
-    push(@obst_reginit, "  ".$class_name."_regs[$idx].reg_class = &$arch\_reg_classes[CLASS_$class_name];\n");
+    push(@obst_reginit, "  ".$class_name."_regs[$idx].reg_class = $class_ptr;\n");
     push(@obst_reginit, "  ".$class_name."_regs[$idx].index     = $idx;\n");
     push(@obst_reginit, "  ".$class_name."_regs[$idx].type      = ".$rt[$_->{"type"}].";\n\n");
     $idx++;
@@ -79,6 +143,8 @@ foreach my $class_name (keys(%reg_classes)) {
   $class_idx++;
 }
 
+push(@obst_header_all, "\n/* node specific requirements */\n");
+
 # generate node-register constraints
 foreach my $op (keys(%nodes)) {
   my %n = %{ $nodes{"$op"} };
@@ -89,6 +155,8 @@ foreach my $op (keys(%nodes)) {
 
   push(@obst_req, "/* IN requirements for '$op' */\n");
 
+  # we need to remember the classes of the IN constraints for
+  # OUT constraints like "in_s1"
   my @inidx_class;
 
   # check for argument requirements
@@ -98,15 +166,19 @@ foreach my $op (keys(%nodes)) {
     for (my $idx = 0; $idx <= $#in; $idx++) {
       my $class = undef;
 
-      push(@obst_req, "static const arch_register_req_t ".$op."_reg_req_in_$idx = {\n");
+      my $tmp2 = "const arch_register_req_t _".$op."_reg_req_in_$idx = ";
+
+      $tmp = "const arch_register_req_t *".$op."_reg_req_in_$idx = ";
+
+      push(@obst_header_all, "extern const arch_register_req_t *".$op."_reg_req_in_$idx;\n");
 
       if ($in[$idx] eq "none") {
         push(@inidx_class, "none");
-        push(@obst_req, "  arch_register_req_type_none,\n  NULL,\n  { NULL }");
+        $tmp .= "&ia32_default_req_none;\n";
       }
       elsif (is_reg_class($in[$idx])) {
         push(@inidx_class, $in[$idx]);
-        push(@obst_req, "  arch_register_req_type_normal,\n  &$arch\_reg_classes[CLASS_$arch\_".$in[$idx]."],\n  { NULL }");
+        $tmp .= "&ia32_default_req_".$arch."_".$in[$idx].";\n";
       }
       else {
         $class = build_subset_class_func($op, $idx, 1, $in[$idx]);
@@ -114,10 +186,13 @@ foreach my $op (keys(%nodes)) {
           die("Could not build subset for IN requirements '$op' pos $idx ... exiting.\n");
         }
         push(@inidx_class, $class);
-        push(@obst_req, "  arch_register_req_type_limited,\n  &$arch\_reg_classes[CLASS_$arch\_".$class."],\n  { limit_reg_".$op."_in_".$idx." }");
+        $tmp  .= "&_".$op."_reg_req_in_$idx;\n";
+        $tmp2 .= " {\n  arch_register_req_type_limited,\n  &$arch\_reg_classes[CLASS_$arch\_".$class."],\n  { limit_reg_".$op."_in_".$idx." }\n};\n";
+
+        $tmp   = $tmp2.$tmp;
       }
 
-      push(@obst_req, "\n};\n\n");
+      push(@obst_req, $tmp."\n");
     }
   }
 
@@ -130,47 +205,58 @@ foreach my $op (keys(%nodes)) {
     for (my $idx = 0; $idx <= $#out; $idx++) {
       my $class = undef;
 
-      push(@obst_req, "static const arch_register_req_t ".$op."_reg_req_out_$idx = {\n");
+      my $tmp2 = "const arch_register_req_t _".$op."_reg_req_out_$idx = ";
+
+      $tmp = "const arch_register_req_t *".$op."_reg_req_out_$idx = ";
+
+      push(@obst_header_all, "extern const arch_register_req_t *".$op."_reg_req_out_$idx;\n");
 
       if ($out[$idx] eq "none") {
-        push(@obst_req, "  arch_register_req_type_none,\n  NULL,\n  { NULL }");
+        $tmp .= "&ia32_default_req_none;\n";
       }
       elsif (is_reg_class($out[$idx])) {
-        push(@obst_req, "  arch_register_req_type_normal,\n  &$arch\_reg_classes[CLASS_$arch\_".$out[$idx]."],\n  { NULL }");
+        $tmp .= "&ia32_default_req_".$arch."_".$out[$idx].";\n";
       }
       elsif ($out[$idx] =~ /^(!)?in_s(\d+)/) { # this is a "should be (un)equal to register at in_X"
-        push(@obst_req, "  arch_register_req_type_".($1 ? "un" : "")."equal,\n");
-        push(@obst_req, "  &$arch\_reg_classes[CLASS_$arch\_".$inidx_class[$2 - 1]."],\n");
-        push(@obst_req, "  { ".($2 - 1)." }");
+        $tmp  .= "&_".$op."_reg_req_out_$idx;\n";
+        $tmp2 .= " {\n";
+        $tmp2 .= "  arch_register_req_type_".($1 ? "un" : "")."equal,\n";
+        $tmp2 .= "  &$arch\_reg_classes[CLASS_$arch\_".$inidx_class[$2 - 1]."],\n";
+        $tmp2 .= "  { ".($2 - 1)." }\n};\n";
+
+        $tmp   = $tmp2.$tmp
       }
       else {
         $class = build_subset_class_func($op, $idx, 0, $out[$idx]);
         if (!defined $class) {
           die("Could not build subset for OUT requirements '$op' pos $idx ... exiting.\n");
         }
-        push(@obst_req, "  arch_register_req_type_limited,\n  &$arch\_reg_classes[CLASS_$arch\_".$class."],\n  { limit_reg_".$op."_out_".$idx." }");
+        $tmp  .= "&_".$op."_reg_req_out_$idx;\n";
+        $tmp2 .= " {\n  arch_register_req_type_limited,\n  &$arch\_reg_classes[CLASS_$arch\_".$class."],\n  { limit_reg_".$op."_out_".$idx." }\n};\n";
+
+        $tmp   = $tmp2.$tmp
       }
 
-      push(@obst_req, "\n};\n\n");
+      push(@obst_req, $tmp."\n");
     }
   }
 }
 
 
 
-# generate header file
-open(OUT, ">$target_h") || die("Could not open $target_h, reason: $!\n");
+# generate header _t (internal usage) file
+open(OUT, ">$target_h_t") || die("Could not open $target_h_t, reason: $!\n");
 
 my $creation_time = localtime(time());
 
-my $tmp = uc($arch);
+$tmp = uc($arch);
 
 print OUT<<EOF;
-#ifndef _GEN_$tmp\_REGALLOC_IF_H_
-#define _GEN_$tmp\_REGALLOC_IF_H_
+#ifndef _GEN_$tmp\_REGALLOC_IF_T_H_
+#define _GEN_$tmp\_REGALLOC_IF_T_H_
 
 /**
- * Generated register classes from spec
+ * Generated register classes from spec.
  *
  * DO NOT EDIT THIS FILE, your changes will be lost.
  * Edit $specfile instead.
@@ -178,14 +264,52 @@ print OUT<<EOF;
  * date:       $creation_time
  */
 
+#include "../bearch.h"
+
 EOF
 
-print OUT @obst_regtypes;
+print OUT @obst_regdef, "\n";
+
+print OUT @obst_classdef, "\n";
+
+print OUT @obst_regtypes, "\n";
+
+print OUT @obst_defreq_head, "\n";
 
 print OUT "void ".$arch."_register_init(void);\n\n";
 
+print OUT "\n#endif /* _GEN_$tmp\_REGALLOC_IF_T_H_ */\n";
+
+
+
+# generate header (external usage) file
+open(OUT, ">$target_h") || die("Could not open $target_h, reason: $!\n");
+
+$creation_time = localtime(time());
+
+print OUT<<EOF;
+#ifndef _GEN_$tmp\_REGALLOC_IF_H_
+#define _GEN_$tmp\_REGALLOC_IF_H_
+
+/**
+ * Contains additional external requirements defs for external includes.
+ *
+ * DO NOT EDIT THIS FILE, your changes will be lost.
+ * Edit $specfile instead.
+ * created by: $0 $specfile $target_dir
+ * date:       $creation_time
+ */
+
+#include "gen_$arch\_regalloc_if_t.h"
+
+EOF
+
+print OUT @obst_header_all;
+
 print OUT "\n#endif /* _GEN_$tmp\_REGALLOC_IF_H_ */\n";
 
+close(OUT);
+
 
 
 # generate c inline file
@@ -205,12 +329,10 @@ print OUT<<EOF;
  * date:       $creation_time
  */
 
-#include "gen_$arch\_regalloc_if.h"
+#include "gen_$arch\_regalloc_if_t.h"
 
 EOF
 
-print OUT @obst_classdef, "\n";
-
 print OUT "arch_register_class_t $arch\_reg_classes[] = {\n  ".join(",\n  ", @obst_regclasses)."\n};\n\n";
 
 print OUT "void ".$arch."_register_init(void) {\n";