- my $neg = undef;
- my $class = "";
- my $temp;
-
- # build function header
- my $op = shift;
- my $idx = shift;
- my $in = shift;
- push(@obst_limit_func, "/* limit the possible registers for ".($in ? "IN" : "OUT")." $idx at op $op */\n");
- push(@obst_limit_func, "int limit_reg_".$op."_".($in ? "in" : "out")."_".$idx."(const ir_node *irn, int pos, bitset_t *bs) {\n");
-
- my @regs = split(/ /, shift);
-
- # set/unset registers
- foreach (@regs) {
- # check for negate
-
- if (substr($_, 0, 1) eq "!") {
- if (defined($neg) && $neg == 0) {
- # we have seen a positiv constraint as first one but this one is negative
- # this doesn't make sense
- print STDERR "Mixed positive and negative constraints for the same slot are not allowed.\n";
- return undef;
- }
-
- if (!defined($neg)) {
- push(@obst_limit_func, " bs = bitset_set_all(bs); /* allow all register (negative constraints given) */\n");
- }
-
- $_ = substr($_, 1); # skip '!'
- $neg = 1;
- }
- else {
- if (defined($neg) && $neg == 1) {
- # we have seen a negative constraint as first one but this one is positive
- # this doesn't make sense
- print STDERR "Mixed positive and negative constraints for the same slot are not allowed.\n";
- return undef;
- }
-
- if (!defined($neg)) {
- push(@obst_limit_func, " bs = bitset_clear_all(bs); /* disallow all register (positive constraints given) */\n");
- }
- $neg = 0;
- }
-
- # check if register belongs to one of the given classes
- $temp = get_reg_class($_);
- if (!defined($temp)) {
- print STDERR "Unknown register '$_'!\n";
- return undef;
- }
-
- # set class
- if (!$class) {
- $class = $temp;
- }
- elsif ($class ne $temp) {
- # all registers must belong to the same class
- print STDERR "Registerclass mismatch. '$_' is not member of class '$class'.\n";
- return undef;
- }
-
- if ($neg == 1) {
- push(@obst_limit_func, " bitset_clear(bs, ".get_reg_index($_)."); /* disallow $_ */\n");
- }
- else {
- push(@obst_limit_func, " bitset_set(bs, ".get_reg_index($_)."); /* allow $_ */\n");
- }
- }
-
- push(@obst_limit_func, "\n return ".($neg ? scalar(@{ $reg_classes{"$class"} }) - scalar(@regs) : scalar(@regs)).";\n");
- push(@obst_limit_func, "}\n\n");
-
- return $class;
+ my $neg = undef;
+ my $class = undef;
+ my $has_limit = 0;
+ my $same_pos = undef;
+ my $different_pos = undef;
+ my $temp;
+ my @obst_init;
+ my @obst_limits;
+ my @obst_ignore;
+ my @limit_array;
+
+ # build function header
+ my $n = shift;
+ my $op = shift;
+ my $idx = shift;
+ my $in = shift;
+
+ my $outin = $in ? "out" : "in";
+ my @regs = split(/ /, shift);
+
+ my @idx_class = build_inout_idx_class($n, $op, $outin);
+
+ # set/unset registers
+CHECK_REQS: foreach (@regs) {
+ if (/(!)?$outin\_r(\d+)/) {
+ if (($1 && defined($different_pos)) || (!$1 && defined($same_pos))) {
+ print STDERR "Multiple in/out references of same type in one requirement not allowed.\n";
+ return (undef, undef, undef, undef);
+ }
+
+ if ($1) {
+ $different_pos = $in ? -$2 : $2 - 1;
+ }
+ else {
+ $same_pos = $in ? -$2 : $2 - 1;
+ }
+
+ $class = $idx_class[$2 - 1];
+ next CHECK_REQS;
+ }
+ elsif (/!in/) {
+ $class = $idx_class[0];
+ return ($class, 0, undef, 666);
+ }
+
+ # check for negate
+ if (substr($_, 0, 1) eq "!") {
+ if (defined($neg) && $neg == 0) {
+ # we have seen a positiv constraint as first one but this one is negative
+ # this doesn't make sense
+ print STDERR "Mixed positive and negative constraints for the same slot are not allowed.\n";
+ return (undef, undef, undef, undef);
+ }
+
+ if (!defined($neg)) {
+ $has_limit = 1;
+ }
+
+ $_ = substr($_, 1); # skip '!'
+ $neg = 1;
+ } else {
+ if (defined($neg) && $neg == 1) {
+ # we have seen a negative constraint as first one but this one is positive
+ # this doesn't make sense
+ print STDERR "Mixed positive and negative constraints for the same slot are not allowed.\n";
+ return (undef, undef, undef, undef);
+ }
+
+ $has_limit = 1;
+ $neg = 0;
+ }
+
+ # check if register belongs to one of the given classes
+ $temp = get_reg_class($_);
+ if (!defined($temp)) {
+ print STDERR "Unknown register '$_'!\n";
+ return (undef, undef, undef, undef);
+ }
+
+ # set class
+ if (!defined($class)) {
+ $class = $temp;
+ } elsif ($class ne $temp) {
+ # all registers must belong to the same class
+ print STDERR "Registerclass mismatch. '$_' is not member of class '$class'.\n";
+ return (undef, undef, undef, undef);
+ }
+
+ # calculate position inside the initializer bitfield (only 32 bits per
+ # element)
+ my $regidx = get_reg_index($_);
+ my $arrayp = $regidx / 32;
+ push(@{$limit_array[$arrayp]}, $_);
+ }
+
+ # don't allow ignore regs in negative constraints
+ if($neg) {
+ my @cur_class = @{ $reg_classes{"$class"} };
+ for (my $idx = 0; $idx <= $#cur_class; $idx++) {
+ if (defined($cur_class[$idx]{"type"}) && ($cur_class[$idx]{"type"} & 4)) {
+ my $reg = $cur_class[$idx]{"name"};
+ my $regix = get_reg_index($reg);
+ my $arrayp = $regix / 32;
+ push(@{$limit_array[$arrayp]}, $reg);
+ }
+ }
+ }
+
+ if ($has_limit == 1) {
+ push(@obst_limit_func, "static const unsigned limit_reg_${op}_".($in ? "in" : "out")."_${idx}[] = { ");
+ my $first = 1;
+ my $limitbitsetlen = $regclass2len{$class};
+ my $limitarraylen = $limitbitsetlen / 32 + ($limitbitsetlen % 32 > 0 ? 1 : 0);
+ for(my $i = 0; $i < $limitarraylen; $i++) {
+ my $limitarraypart = $limit_array[$i];
+ if($first) {
+ $first = 0;
+ } else {
+ push(@obst_limit_func, ", ");
+ }
+ my $temp;
+ if($neg) {
+ $temp = "0xFFFFFFFF";
+ }
+ foreach my $reg (@{$limitarraypart}) {
+ if($neg) {
+ $temp .= " & ~";
+ } elsif(defined($temp)) {
+ $temp .= " | ";
+ }
+ $temp .= "BIT(REG_".uc(${reg}).")";
+ }
+ if(defined($temp)) {
+ push(@obst_limit_func, "${temp}");
+ } else {
+ push(@obst_limit_func, "0");
+ }
+ }
+ push(@obst_limit_func, " };\n");
+ }
+
+ return ($class, $has_limit, $same_pos, $different_pos);
+}
+
+###
+# 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;