$temp = " asmop_attr *attr;\n";
$temp .= " ir_node *res;\n";
$temp .= " ir_node *in[$arity];\n" if ($arity > 0);
+
+ undef my $in_req_var;
+ undef my $out_req_var;
+ undef my $slots_var;
+
+ # set up static variables for requirements and registers
+ if (exists($n{"reg_req"})) {
+ my %req = %{ $n{"reg_req"} };
+ my $idx;
+
+ undef my @in;
+ @in = @{ $req{"in"} } if (exists($req{"in"}));
+ undef my @out;
+ @out = @{ $req{"out"} } if exists(($req{"out"}));
+
+ if (@in) {
+ $in_req_var = "_in_req_$op";
+ $temp .= " static const $arch\_register_req_t *".$in_req_var."[] =\n {\n";
+ for ($idx = 0; $idx <= $#in; $idx++) {
+ $temp .= " ".$op."_reg_req_in_".$idx.",\n";
+ }
+ $temp .= " };\n";
+ }
+
+ if (@out) {
+ $out_req_var = "_out_req_$op";
+ $slots_var = "_slots_$op";
+
+ $temp .= " static const $arch\_register_req_t *".$out_req_var."[] =\n {\n";
+ for ($idx = 0; $idx <= $#out; $idx++) {
+ $temp .= " ".$op."_reg_req_out_".$idx.",\n";
+ }
+ $temp .= " };\n";
+ $temp .= " static arch_register_t *".$slots_var."[".($#out + 1)."];\n";
+ }
+ }
+
$temp .= "\n";
$temp .= " if (!op_$op) {\n";
$temp .= " assert(0);\n";
# allocate memory and set pointer to register requirements
if (exists($n{"reg_req"})) {
my %req = %{ $n{"reg_req"} };
- my $idx;
undef my @in;
@in = @{ $req{"in"} } if (exists($req{"in"}));
undef my @out;
@out = @{ $req{"out"} } if exists(($req{"out"}));
+ $temp .= "\n /* set IN register requirements */\n";
if (@in) {
- $temp .= "\n /* allocate memory for IN register requirements and assigned registers */\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 = ".$in_req_var.";\n";
+ }
+ else {
+ $temp .= " attr->in_req = NULL;\n";
}
+ $temp .= "\n /* set OUT register requirements and get space for registers */\n";
if (@out) {
- $temp .= "\n /* allocate memory for OUT register requirements and 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->n_res = ".($#out + 1).";\n";
+ $temp .= " attr->out_req = ".$out_req_var.";\n";
+ $temp .= " attr->slots = ".$slots_var.";\n";
+ $temp .= " attr->n_res = ".($#out + 1).";\n";
}
else {
- $temp .= " attr->n_res = 0;\n";
+ $temp .= " attr->out_req = NULL;\n";
+ $temp .= " attr->slots = NULL;\n";
+ $temp .= " attr->n_res = 0;\n";
}
}
open(OUT, ">$target_c") || die("Could not open $target_c, reason: $!\n");
+print OUT "#include \"gen_$arch\_regalloc_if_t.h\"\n\n";
print OUT @obst_cmp_attr;
print OUT "\n";
print OUT @obst_opvar;
print OUT "\n";
print OUT @obst_get_opvar;
print OUT "\n";
-print OUT "int is_".$arch."_irn(const ir_node *node) {\n if (".join(" ||\n ", @obst_is_archirn).")\n return 1;\n else\n return 0;\n}\n\n";
+
+print OUT<<ENDOFISIRN;
+
+static opcode ia32_opcode_start = -1;
+static opcode ia32_opcode_end = -1;
+
+int is_$arch\_irn(const ir_node *node) {
+ opcode opc = get_irn_opcode(node);
+
+ assert(ia32_opcode_start > 0 && "missing opcode init");
+ assert(ia32_opcode_end > 0 && "missing opcode init");
+
+ if (opc > ia32_opcode_start && opc < ia32_opcode_end)
+ return 1;
+
+ return 0;
+}
+
+ENDOFISIRN
+
print OUT @obst_constructor;
print OUT<<ENDOFMAIN;
#define H irop_flag_highlevel
#define c irop_flag_constlike
- ir_op_ops ops;
+ ir_op_ops ops;
+
+ ia32_opcode_start = get_next_ir_opcode();
ENDOFMAIN
print OUT @obst_new_irop;
+print OUT "\n ia32_opcode_end = get_next_ir_opcode();\n";
print OUT "}\n";
close(OUT);
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 @obst_projnum_map; # stack for mapping register projnums to requirements
+my @obst_requirement_def; # stack for requirement name defines
my $numregs;
my $class_ptr;
$tmp .= " 0\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 $arch\_default_req_none;\n");
push(@obst_classdef, "#define N_CLASSES ".scalar(keys(%reg_classes))."\n");
$tmp .= " 0\n";
$tmp .= "};\n\n";
push(@obst_req, $tmp);
-
- push(@obst_header_all, "\nextern const $arch\_register_req_t $arch\_default_req_$class_name;\n");
+ push(@obst_header_all, "extern const $arch\_register_req_t $arch\_default_req_$class_name;\n");
my $idx = 0;
push(@obst_reginit, " /* Init of all registers in class '$class_name' */\n\n");
$tmp .= " 0\n";
$tmp .= "};\n\n";
push(@obst_req, $tmp);
-
- push(@obst_header_all, "extern const $arch\_register_req_t $arch\_default_req_$class_name\_".$_->{"name"}.";\n");
+ push(@obst_header_all,"extern const $arch\_register_req_t $arch\_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_regdef, "\n#define N_CALLER_SAVE_REGS ".scalar(@obst_projnum_map)."\n");
push(@obst_header_all, "\nextern const $arch\_register_req_t *$arch\_projnum_reg_req_map[N_CALLER_SAVE_REGS];\n\n");
-push(@obst_header_all, "\n/* node specific requirements */\n");
# generate node-register constraints
foreach my $op (keys(%nodes)) {
* date: $creation_time
*/
-#include "../bearch.h"
-#include "$arch\_nodes_attr.h"
-
EOF
-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 *isa_ptr);\n\n";
+print OUT @obst_requirement_def;
print OUT "\n#endif /* _GEN_$tmp\_REGALLOC_IF_T_H_ */\n";
* date: $creation_time
*/
-#include "gen_$arch\_regalloc_if_t.h"
+#include "../bearch.h"
+#include "$arch\_nodes_attr.h"
EOF
-print OUT @obst_header_all;
+print OUT @obst_regdef, "\n";
+
+print OUT @obst_classdef, "\n";
+
+print OUT @obst_regtypes, "\n";
+
+print OUT "extern arch_register_class_t $arch\_reg_classes[N_CLASSES];\n\n";
+
+print OUT "void ".$arch."_register_init(void *isa_ptr);\n\n";
+
+print OUT @obst_header_all, "\n";
+
+print OUT @obst_defreq_head, "\n";
print OUT "\n#endif /* _GEN_$tmp\_REGALLOC_IF_H_ */\n";
print OUT "}\n\n";
print OUT @obst_limit_func;
+
print OUT @obst_req;
close(OUT);
my $class = undef;
my $tmp2 = "const $arch\_register_req_t _".$op."_reg_req_$inout\_$idx = ";
- my $tmp = "const $arch\_register_req_t *".$op."_reg_req_$inout\_$idx = ";
-
- push(@obst_header_all, "extern const $arch\_register_req_t *".$op."_reg_req_$inout\_$idx;\n");
+ my $tmp = "#define ".$op."_reg_req_$inout\_$idx ";
if ($reqs[$idx] eq "none") {
- $tmp .= "&$arch\_default_req_none;\n";
+ $tmp .= "&$arch\_default_req_none\n";
}
elsif (is_reg_class($reqs[$idx])) {
- $tmp .= "&$arch\_default_req_".$arch."_".$reqs[$idx].";\n";
+ $tmp .= "&$arch\_default_req_".$arch."_".$reqs[$idx]."\n";
}
else {
my @req_type_mask;
if (defined($pos)) {
push(@req_type_mask, "arch_register_req_type_should_be_".($same ? "same" : "different"));
}
- $tmp .= "&_".$op."_reg_req_$inout\_$idx;\n";
+ $tmp .= "&_".$op."_reg_req_$inout\_$idx\n";
$tmp2 .= " {\n";
$tmp2 .= " {\n";
$tmp2 .= " ".join(" | ", @req_type_mask).",\n";
$tmp2 .= " },\n";
$tmp2 .= " ".(defined($pos) ? $pos : "0")."\n};\n";
- $tmp = $tmp2.$tmp;
+ push(@obst_req, $tmp2."\n");
+ push(@obst_header_all, "extern const $arch\_register_req_t _".$op."_reg_req_$inout\_$idx;\n");
}
- push(@obst_req, $tmp."\n");
+ push(@obst_requirement_def, $tmp);
}
}
}
if ($has_limit == 1) {
+ push(@obst_header_all, "void limit_reg_".$op."_".($in ? "in" : "out")."_".$idx."(void *_unused, bitset_t *bs);\n");
+
push(@obst_limit_func, "/* limit the possible registers for ".($in ? "IN" : "OUT")." $idx at op $op */\n");
push(@obst_limit_func, "void limit_reg_".$op."_".($in ? "in" : "out")."_".$idx."(void *_unused, bitset_t *bs) {\n");
push(@obst_limit_func, @temp_obst);