generate_regalloc_if.pl 18.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/perl -w

# This script generates C code which emits assembler code for the
# assembler ir nodes. It takes a "emit" key from the node specification
# and substitutes lines starting with . with a corresponding fprintf().
# Creation: 2005/11/14
# $Id$

use strict;
use Data::Dumper;

my $specfile   = $ARGV[0];
my $target_dir = $ARGV[1];

our $arch;
our %reg_classes;
our %nodes;

# include spec file

my $return;

no strict "subs";
unless ($return = do $specfile) {
25
26
27
	warn "couldn't parse $specfile: $@" if $@;
	warn "couldn't do $specfile: $!"    unless defined $return;
	warn "couldn't run $specfile"       unless $return;
28
29
30
}
use strict "subs";

Christian Würdig's avatar
Christian Würdig committed
31
32
33
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";
34

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 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");
		}

57
58
59
60
		if ($t & 8) {
			push(@types, "arch_register_type_joker");
		}

61
62
63
		return join(" | ", @types);
	}
}
64
65

# stacks for output
66
67
my @obst_regtypes_def; # stack for the register type variables definitions
my @obst_regtypes_decl;# stack for the register type variables declarations
68
my @obst_regclasses;   # stack for the register class variables
Christian Würdig's avatar
Christian Würdig committed
69
70
my @obst_classdef;     # stack to define a name for a class index
my @obst_regdef;       # stack to define a name for a register index
71
72
73
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
Christian Würdig's avatar
Christian Würdig committed
74
75
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
76
my @obst_requirement_def;  # stack for requirement name defines
77
78

my $numregs;
Christian Würdig's avatar
Christian Würdig committed
79
my $class_ptr;
80
81
my $class_idx = 0;

Christian Würdig's avatar
Christian Würdig committed
82
83
my $tmp;

84
85
my %reg2class;

Christian Würdig's avatar
Christian Würdig committed
86
87
# there is a default NONE requirement
$tmp = "/* Default NONE register requirements */\n";
88
89
$tmp .= "const $arch\_register_req_t $arch\_default_req_none = {\n";
$tmp .= "  {\n";
90
91
92
93
94
95
$tmp .= "    arch_register_req_type_none,  /* register type  */\n";
$tmp .= "    NULL,                         /* register class */\n";
$tmp .= "    NULL,                         /* limit function */\n";
$tmp .= "    NULL,                         /* limit environment */\n";
$tmp .= "    NULL,                         /* node for same */\n";
$tmp .= "    NULL                          /* node for different */\n";
96
$tmp .= "  },\n";
97
98
$tmp .= "  0,                              /* same pos */\n";
$tmp .= "  0                               /* different pos */\n";
Christian Würdig's avatar
Christian Würdig committed
99
100
$tmp .= "};\n\n";
push(@obst_req, $tmp);
101
push(@obst_header_all, "extern const $arch\_register_req_t $arch\_default_req_none;\n");
Christian Würdig's avatar
Christian Würdig committed
102

103
push(@obst_classdef, "enum reg_classes {\n");
Christian Würdig's avatar
Christian Würdig committed
104

105
my $class_mode;
106

Christian Würdig's avatar
Christian Würdig committed
107
# generate register type and class variable, init function and default requirements
108
foreach my $class_name (keys(%reg_classes)) {
109
110
111
112
113
114
	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."]";
115
	$class_mode = pop(@class)->{"mode"};
116

117
118
	push(@obst_regtypes_decl, "extern arch_register_t ".$class_name."_regs[$numregs];\n");
	push(@obst_regtypes_def, "arch_register_t ".$class_name."_regs[$numregs];\n");
119

120
	push(@obst_classdef, "  CLASS_$class_name = $class_idx,\n");
121
	push(@obst_regclasses, "{ \"$class_name\", $numregs, NULL, ".$class_name."_regs }");
122
123
124
125
126
127
128

	# 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 $arch\_default_req_$class_name = {\n";
	$tmp .= "  {\n";
	$tmp .= "    arch_register_req_type_normal,\n";
	$tmp .= "    $class_ptr,\n";
129
130
131
132
	$tmp .= "    NULL,                    /* limit function */ \n";
	$tmp .= "    NULL,                    /* limit environment */\n";
	$tmp .= "    NULL,                    /* node for same */\n";
	$tmp .= "    NULL                     /* node for different */\n";
133
	$tmp .= "  },\n";
134
135
	$tmp .= "  0,                         /* same pos */\n";
	$tmp .= "  0                          /* different pos */\n";
136
137
	$tmp .= "};\n\n";
	push(@obst_req, $tmp);
138
	push(@obst_header_all, "extern const $arch\_register_req_t $arch\_default_req_$class_name;\n");
139
140
141

	my $idx = 0;
	push(@obst_reginit, "  /* Init of all registers in class '$class_name' */\n\n");
142
143
	push(@obst_reginit, "  /* set largest possible mode for '$class_name' */\n");
	push(@obst_reginit, "  $arch\_reg_classes[CLASS_".$class_name."].mode = $class_mode;\n\n");
144
	push(@obst_regdef, "enum reg_".$class_name."_values {\n");
145
146
147
148
149
150
151
152
153
154
	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
Christian Würdig's avatar
Christian Würdig committed
155
		$tmp = "void $limit_func_name(void *_unused, bitset_t *bs)";
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
		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 .= "}\n\n";
		push(@obst_limit_func, $tmp);

		# push the default requirement struct
		$tmp  = "const $arch\_register_req_t $arch\_default_req_$class_name\_".$_->{"name"}." = {\n";
		$tmp .= "  {\n";
		$tmp .= "    arch_register_req_type_limited,\n";
		$tmp .= "    $class_ptr,\n";
		$tmp .= "    $limit_func_name,\n";
171
172
173
		$tmp .= "    NULL,                     /* limit environment */\n";
		$tmp .= "    NULL,                     /* node for same */\n";
		$tmp .= "    NULL                      /* node for different */\n";
174
		$tmp .= "  },\n";
175
176
		$tmp .= "  0,                          /* same pos */\n";
		$tmp .= "  0                           /* different pos */\n";
177
178
		$tmp .= "};\n\n";
		push(@obst_req, $tmp);
179
		push(@obst_header_all,"extern const $arch\_register_req_t $arch\_default_req_$class_name\_".$_->{"name"}.";\n");
180
181

		$reg2class{$_->{"name"}} = { "class" => $old_classname, "index" => $idx }; # remember reg to class for later use
182
		push(@obst_regdef, "  REG_".uc($_->{"name"})." = $idx,\n");
183
184
185
		push(@obst_reginit, "  ".$class_name."_regs[$idx].name      = \"".$_->{"name"}."\";\n");
		push(@obst_reginit, "  ".$class_name."_regs[$idx].reg_class = $class_ptr;\n");
		push(@obst_reginit, "  ".$class_name."_regs[$idx].index     = $idx;\n");
186
		push(@obst_reginit, "  ".$class_name."_regs[$idx].type      = ".translate_reg_type($_->{"type"}).";\n");
187
		push(@obst_reginit, "\n");
188
189
		$idx++;
	}
190
191
	push(@obst_regdef, "  $numregs = $idx\n");
	push(@obst_regdef, "};\n\n");
192
193

	$class_idx++;
194
195
}

196
197
198
push(@obst_classdef, "  N_CLASSES = ".scalar(keys(%reg_classes))."\n");
push(@obst_classdef, "};\n\n");

199
200
# generate node-register constraints
foreach my $op (keys(%nodes)) {
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
	my %n = %{ $nodes{"$op"} };

	next if (!exists($n{"reg_req"}));

	$op = $arch."_".$op;

	push(@obst_req, "/* IN requirements for '$op' */\n");
	# check for argument requirements
	if (exists($n{"reg_req"}{"in"})) {
		generate_requirements(\%n, $op, "in");
	}

	push(@obst_req, "/* OUT requirements for '$op' */\n");
	# check for result requirements
	if (exists($n{"reg_req"}{"out"})) {
		generate_requirements(\%n, $op, "out");
	}
218
219
220
221
}



Christian Würdig's avatar
Christian Würdig committed
222
223
# generate header _t (internal usage) file
open(OUT, ">$target_h_t") || die("Could not open $target_h_t, reason: $!\n");
224
225
226

my $creation_time = localtime(time());

Christian Würdig's avatar
Christian Würdig committed
227
$tmp = uc($arch);
228
229

print OUT<<EOF;
Christian Würdig's avatar
Christian Würdig committed
230
231
#ifndef _GEN_$tmp\_REGALLOC_IF_T_H_
#define _GEN_$tmp\_REGALLOC_IF_T_H_
232
233

/**
Christian Würdig's avatar
Christian Würdig committed
234
 * Generated register classes from spec.
235
236
237
238
239
240
241
242
243
 *
 * DO NOT EDIT THIS FILE, your changes will be lost.
 * Edit $specfile instead.
 * created by: $0 $specfile $target_dir
 * date:       $creation_time
 */

EOF

244
print OUT @obst_requirement_def;
245

Christian Würdig's avatar
Christian Würdig committed
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
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
 */

268
269
#include "../bearch.h"
#include "$arch\_nodes_attr.h"
Christian Würdig's avatar
Christian Würdig committed
270
271
272

EOF

273
274
275
276
print OUT @obst_regdef, "\n";

print OUT @obst_classdef, "\n";

277
print OUT @obst_regtypes_decl, "\n";
278
279
280
281
282
283
284
285

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";
Christian Würdig's avatar
Christian Würdig committed
286

287
288
print OUT "\n#endif /* _GEN_$tmp\_REGALLOC_IF_H_ */\n";

Christian Würdig's avatar
Christian Würdig committed
289
290
close(OUT);

291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309


# generate c inline file
open(OUT, ">$target_c") || die("Could not open $target_c, reason: $!\n");

$creation_time = localtime(time());

print OUT<<EOF;
/**
 * The generated interface for the register allocator.
 * Contains register classes and types and register constraints
 * for all nodes where constraints were given in spec.
 *
 * DO NOT EDIT THIS FILE, your changes will be lost.
 * Edit $specfile instead.
 * created by: $0 $specfile $target_dir
 * date:       $creation_time
 */

310
#include "gen_$arch\_regalloc_if.h"
311
312
#include "bearch_$arch\_t.h"   /* we need this to put the caller saved registers into the isa set */
#include "$arch\_map_regs.h"
313
#include "irmode.h"
314
315
316
317
318

EOF

print OUT "arch_register_class_t $arch\_reg_classes[] = {\n  ".join(",\n  ", @obst_regclasses)."\n};\n\n";

319
320
print OUT @obst_regtypes_def, "\n";

321
print OUT "void ".$arch."_register_init(void *isa_ptr) {\n";
322
323
324
325
print OUT @obst_reginit;
print OUT "}\n\n";

print OUT @obst_limit_func;
326

327
328
329
330
print OUT @obst_req;

close(OUT);

331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
###
# Remember the register class for each index in the given requirements.
# We need this information for requirements like "in_sX" or "out_dX"
# @return array of classes corresponding to the requirement for each index
###
sub build_inout_idx_class {
	my $n     = shift;
	my $op    = shift;
	my $inout = shift;
	my @idx_class;

	if (exists($n->{"reg_req"}{"$inout"})) {
		my @reqs = @{ $n->{"reg_req"}{"$inout"} };

		for (my $idx = 0; $idx <= $#reqs; $idx++) {
			my $class = undef;

			if ($reqs[$idx] eq "none") {
				$class = "none";
			}
			elsif (is_reg_class($reqs[$idx])) {
				$class = $reqs[$idx];
			}
			else {
				my @regs = split(/ /, $reqs[$idx]);
GET_CLASS:		foreach my $reg (@regs) {
357
					if ($reg =~ /!?(in|out)\_r\d+/ || $reg =~ /!in/) {
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
						$class = "UNKNOWN_CLASS";
					}
					else {
						$class = get_reg_class($reg);
						if (!defined $class) {
							die("Could not get ".uc($inout)." register class for '$op' pos $idx (reg $reg) ... exiting.\n");
						}
						else {
							last GET_CLASS;
						} # !defined class
					} # if (reg =~ ...
				} # foreach
			} # if

			push(@idx_class, $class);
		} # for
	} # if

	return @idx_class;
}
378

379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
###
# Generates the requirements for the given description
###
sub generate_requirements {
	my $n     = shift;
	my $op    = shift;
	my $inout = shift;

	# get classes for the complementary direction
	my $outin     = ($inout eq "in") ? "out" : "in";

	my @reqs = @{ $n->{"reg_req"}{"$inout"} };

	for (my $idx = 0; $idx <= $#reqs; $idx++) {
		my $class = undef;

		my $tmp2 = "const $arch\_register_req_t _".$op."_reg_req_$inout\_$idx = ";
396
		my $tmp  = "#define ".$op."_reg_req_$inout\_$idx ";
397
398

		if ($reqs[$idx] eq "none") {
399
			$tmp .= "&$arch\_default_req_none\n";
400
		}
Christian Würdig's avatar
Christian Würdig committed
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
		elsif ($reqs[$idx] =~ /^new_reg_(.*)$/) {
			if (is_reg_class($1)) {
				$tmp  .=  "&_".$op."_reg_req_$inout\_$idx\n";
				$tmp2 .= "{\n";
				$tmp2 .= "  {\n";
				$tmp2 .= "    arch_register_req_type_should_be_different_from_all,\n";
				$tmp2 .= "    &$arch\_reg_classes[CLASS_$arch\_".$1."],\n";
				$tmp2 .= "    NULL,        /* limit function */\n";
				$tmp2 .= "    NULL,        /* limit environment */\n";
				$tmp2 .= "    NULL,        /* same node */\n";
				$tmp2 .= "    NULL         /* different node */\n";
				$tmp2 .= "  },\n";
				$tmp2 .= "  0,\n";
				$tmp2 .= "  0\n";
				$tmp2 .= "};\n";

				push(@obst_req, $tmp2."\n");
				push(@obst_header_all, "extern const $arch\_register_req_t _".$op."_reg_req_$inout\_$idx;\n");
			}
			else {
				print STDERR "Invalid register class '$1' given in OUT requirement $idx for '$op'.\n";
			}
		}
424
		elsif (is_reg_class($reqs[$idx])) {
425
			$tmp .= "&$arch\_default_req_".$arch."_".$reqs[$idx]."\n";
426
427
428
		}
		else {
			my @req_type_mask;
429
430
			my ($class, $has_limit, $same_pos, $different_pos) = build_subset_class_func($n, $op, $idx, (($inout eq "in") ? 1 : 0), $reqs[$idx]);

431
432
433
			if (!defined($class)) {
				die("Could not build subset for ".uc($inout)." requirements '$op' pos $idx ... exiting.\n");
			}
434

435
436
437
			if ($has_limit) {
				push(@req_type_mask, "arch_register_req_type_limited");
			}
438
439
			if (defined($same_pos)) {
				push(@req_type_mask, "arch_register_req_type_should_be_same");
440
			}
441
			if (defined($different_pos)) {
442
443
444
445
446
447
448
				if ($different_pos == 666) {
					push(@req_type_mask, "arch_register_req_type_should_be_different_from_all");
					undef $different_pos;
				}
				else {
					push(@req_type_mask, "arch_register_req_type_should_be_different");
				}
449
450
			}

451
			$tmp  .= "&_".$op."_reg_req_$inout\_$idx\n";
452
			$tmp2 .= "{\n";
453
454
455
			$tmp2 .= "  {\n";
			$tmp2 .= "    ".join(" | ", @req_type_mask).",\n";
			$tmp2 .= "    &$arch\_reg_classes[CLASS_$arch\_".$class."],\n";
456
			$tmp2 .= "    ".($has_limit ? "limit_reg_".$op."_$inout\_".$idx : "NULL").",\n";
457
458
459
			$tmp2 .= "    NULL,        /* limit environment */\n";
			$tmp2 .= "    NULL,        /* same node */\n";
			$tmp2 .= "    NULL         /* different node */\n";
460
			$tmp2 .= "  },\n";
461
462
463
			$tmp2 .= "  ".(defined($same_pos) ? $same_pos : "0").",\n";
			$tmp2 .= "  ".(defined($different_pos) ? $different_pos : "0")."\n";
			$tmp2 .= "};\n";
464

465
466
			push(@obst_req, $tmp2."\n");
			push(@obst_header_all, "extern const $arch\_register_req_t _".$op."_reg_req_$inout\_$idx;\n");
467
468
		}

469
		push(@obst_requirement_def, $tmp);
470
471
472
	}

}
473
474
475
476
477
478

###
# Determines whether $name is a specified register class or not.
# @return 1 if name is register class, 0 otherwise
###
sub is_reg_class {
479
480
481
	my $name = shift;
	return 1 if exists($reg_classes{"$name"});
	return 0;
482
483
484
485
486
487
488
}

###
# Returns the register class for a given register.
# @return class or undef
###
sub get_reg_class {
489
	my $reg = shift;
490
	$reg = substr($reg, 1) if ($reg =~ /!.*/);
491
492
	return $reg2class{"$reg"}{"class"} if (exists($reg2class{"$reg"}));
	return undef;
493
494
495
496
497
498
499
}

###
# Returns the index of a given register within it's register class.
# @return index or undef
###
sub get_reg_index {
500
501
502
	my $reg = shift;
	return $reg2class{"$reg"}{"index"} if (exists($reg2class{"$reg"}));
	return undef;
503
504
505
506
507
}

###
# Generates the function for a given $op and a given IN-index
# which returns a subset of possible register from a register class
508
509
# @return classname from which the subset is derived or undef and
#         pos which corresponds to in/out reference position or undef
510
511
###
sub build_subset_class_func {
512
513
514
515
516
	my $neg           = undef;
	my $class         = undef;
	my $has_limit     = 0;
	my $same_pos      = undef;
	my $different_pos = undef;
517
	my $temp;
518
519
520
	my @obst_init;
	my @obst_limits;
	my @obst_ignore;
521
522


523
524
525
526
527
	# build function header
	my $n   = shift;
	my $op  = shift;
	my $idx = shift;
	my $in  = shift;
528
529
530
531
532
533
534
535
536

	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+)/) {
537
			if (($1 && defined($different_pos)) || (!$1 && defined($same_pos))) {
538
				print STDERR "Multiple in/out references of same type in one requirement not allowed.\n";
539
540
				return (undef, undef, undef, undef);
			}
541
542
543
544
545
546
547
548

			if ($1) {
				$different_pos = $in ? -$2 : $2 - 1;
			}
			else {
				$same_pos = $in ? -$2 : $2 - 1;
			}

549
550
551
			$class = $idx_class[$2 - 1];
			next CHECK_REQS;
		}
552
553
554
555
		elsif (/!in/) {
			$class = $idx_class[0];
			return ($class, 0, undef, 666);
		}
556
557
558
559
560
561
562
563
564
565
566
567

		# 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;
568
				push(@obst_init, "  bs = bitset_set_all(bs);     /* allow all register (negative constraints given) */\n");
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
			}

			$_   = 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);
			}

			if (!defined($neg)) {
				$has_limit = 1;
584
				push(@obst_init, "  bs = bitset_clear_all(bs);   /* disallow all register (positive constraints given) */\n");
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
			}
			$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);
		}

		if ($neg == 1) {
			$has_limit = 1;
608
			push(@obst_limits, "  bitset_clear(bs, ".get_reg_index($_).");         /* disallow $_ */\n");
609
610
611
		}
		else {
			$has_limit = 1;
612
			push(@obst_limits, "  bitset_set(bs, ".get_reg_index($_).");           /* allow $_ */\n");
613
614
615
		}
	}

616
617
618
	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)) {
619
620
			push(@obst_ignore, "  bitset_clear(bs, ".get_reg_index($cur_class[$idx]{"name"}).");");
			push(@obst_ignore, "         /* disallow ignore reg ".$cur_class[$idx]{"name"}." */\n");
621
622
623
		}
	}

624
	if ($has_limit == 1) {
625
626
		push(@obst_header_all, "void limit_reg_".$op."_".($in ? "in" : "out")."_".$idx."(void *_unused, bitset_t *bs);\n");

627
		push(@obst_limit_func, "/* limit the possible registers for ".($in ? "IN" : "OUT")." $idx at op $op */\n");
Christian Würdig's avatar
Christian Würdig committed
628
		push(@obst_limit_func, "void limit_reg_".$op."_".($in ? "in" : "out")."_".$idx."(void *_unused, bitset_t *bs) {\n");
629
630
631
		push(@obst_limit_func, @obst_init);
		push(@obst_limit_func, @obst_ignore);
		push(@obst_limit_func, @obst_limits);
632
633
634
		push(@obst_limit_func, "}\n\n");
	}

635
	return ($class, $has_limit, $same_pos, $different_pos);
636
}