generate_regalloc_if.pl 17.8 KB
Newer Older
1
2
#!/usr/bin/perl -w

Christian Würdig's avatar
Christian Würdig committed
3
4
# This script generates C code which creates ands sets up functions and
# data structures for the register allocator.
5
6
7
8
9
# Creation: 2005/11/14
# $Id$

use strict;
use Data::Dumper;
Matthias Braun's avatar
Matthias Braun committed
10
use integer;
11
12
13
14
15
16
17

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

our $arch;
our %reg_classes;
our %nodes;
18
our %cpu;
19
our %flags = ();
20
21
22
23
24

# include spec file

my $return;

Matthias Braun's avatar
Matthias Braun committed
25
use strict "subs";
26
unless ($return = do $specfile) {
27
28
29
	die "couldn't parse $specfile: $@" if $@;
	die "couldn't do $specfile: $!"    unless defined $return;
	die "couldn't run $specfile"       unless $return;
30
31
32
}
use strict "subs";

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

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

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

63
64
65
66
		if ($t & 16) {
			push(@types, "arch_register_type_virtual");
		}

Matthias Braun's avatar
Matthias Braun committed
67
68
69
70
		if ($t & 32) {
			push(@types, "arch_register_type_state");
		}

71
72
73
		return join(" | ", @types);
	}
}
74
75

# stacks for output
76
77
my @obst_regtypes_def; # stack for the register type variables definitions
my @obst_regtypes_decl;# stack for the register type variables declarations
78
my @obst_regclasses;   # stack for the register class variables
Christian Würdig's avatar
Christian Würdig committed
79
80
my @obst_classdef;     # stack to define a name for a class index
my @obst_regdef;       # stack to define a name for a register index
81
82
83
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
84
my @obst_header_all;   # stack for some extern struct defs needed for bearch_$arch include
Matthias Braun's avatar
Matthias Braun committed
85
my @obst_header_t;
86
87

my $numregs;
Christian Würdig's avatar
Christian Würdig committed
88
my $class_ptr;
89
90
my $class_idx = 0;

Christian Würdig's avatar
Christian Würdig committed
91
92
my $tmp;

93
my %reg2class;
Matthias Braun's avatar
Matthias Braun committed
94
my %regclass2len;
Christian Würdig's avatar
Christian Würdig committed
95

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

98
my $class_mode;
99

100
# assure, the initialization is done only once
Matthias Braun's avatar
Matthias Braun committed
101
push(@obst_reginit, "\tstatic int run_once = 0;\n");
102
push(@obst_reginit, "\n");
Matthias Braun's avatar
Matthias Braun committed
103
104
105
push(@obst_reginit, "\tif (run_once)\n");
push(@obst_reginit, "\t\treturn;\n");
push(@obst_reginit, "\trun_once = 1;\n");
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
	push(@obst_regtypes_decl, "extern const arch_register_t ${class_name}_regs[$numregs];\n");
118

Matthias Braun's avatar
Matthias Braun committed
119
	push(@obst_classdef, "\tCLASS_$class_name = $class_idx,\n");
120
	push(@obst_regclasses, "{ \"$class_name\", $numregs, NULL, ".$class_name."_regs }");
121
122

	my $idx = 0;
Matthias Braun's avatar
Matthias Braun committed
123
124
	push(@obst_reginit, "\t/* set largest possible mode for '$class_name' */\n");
	push(@obst_reginit, "\t$arch\_reg_classes[CLASS_".$class_name."].mode = $class_mode;\n\n");
125
126
127
	push(@obst_regtypes_def, "const arch_register_t ${class_name}_regs[$numregs] = {\n");

	push(@obst_regdef, "enum reg_${class_name}_indices {\n");
128
	foreach (@class) {
129
130
		my $ucname = uc($_->{"name"});
		my $type = translate_reg_type($_->{"type"});
131
132
		# realname is name if not set by user
		$_->{"realname"} = $_->{"name"} if (! exists($_->{"realname"}));
133
134
135
		my $realname = $_->{realname};
		my $execunitvarname = get_execunit_variable_name($_->{"unit"});

136

137
		$reg2class{$_->{"name"}} = { "class" => $old_classname, "index" => $idx }; # remember reg to class for later use
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
		push(@obst_regdef, "\tREG_${ucname},\n");

		push(@obst_regtypes_def, "\t{\n");
		push(@obst_regtypes_def, "\t\t\"$realname\",\n");
		push(@obst_regtypes_def, "\t\t$class_ptr,\n");
		push(@obst_regtypes_def, "\t\tREG_${ucname},\n");
		push(@obst_regtypes_def, "\t\t$type,\n");
		push(@obst_regtypes_def, "\t\t$execunitvarname\n");
		push(@obst_regtypes_def, "\t},\n");

#		push(@obst_reginit, "\t${class_name}_regs[$idx].name      = \"".$_->{"realname"}."\";\n");
#		push(@obst_reginit, "\t${class_name}_regs[$idx].reg_class = $class_ptr;\n");
#		push(@obst_reginit, "\t${class_name}_regs[$idx].index     = $idx;\n");
#		push(@obst_reginit, "\t${class_name}_regs[$idx].type      = ".translate_reg_type($_->{"type"}).";\n");
#		push(@obst_reginit, "\t${class_name}_regs[$idx].data      = ".get_execunit_variable_name($_->{"unit"}).";\n");
#		push(@obst_reginit, "\n");
154
155
		$idx++;
	}
156
157
	push(@obst_regtypes_def, "};\n");

Matthias Braun's avatar
Matthias Braun committed
158
159
	$regclass2len{$old_classname} = $idx;
	push(@obst_regdef, "\t$numregs = $idx\n");
160
	push(@obst_regdef, "};\n\n");
161
162

	$class_idx++;
163
164
}

165
166
167
168
169
170
171
172
push(@obst_regdef, "enum flag_indices {\n");
foreach my $flag (keys(%flags)) {
	my %f = %{ $flags{$flag} };

	push(@obst_regdef, "\tFLAG_$flag,\n");
}
push(@obst_regdef, "\tFLAG_LAST\n");
push(@obst_regdef, "};\n");
Matthias Braun's avatar
Matthias Braun committed
173
push(@obst_regtypes_decl, "extern arch_flag_t ${arch}_flags[];\n");
174

Matthias Braun's avatar
Matthias Braun committed
175
push(@obst_classdef, "\tN_CLASSES = ".scalar(keys(%reg_classes))."\n");
176
177
push(@obst_classdef, "};\n\n");

178
179
# generate node-register constraints
foreach my $op (keys(%nodes)) {
180
	my %n = %{ $nodes{$op} };
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

	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");
	}
197
198
199
200
}



Christian Würdig's avatar
Christian Würdig committed
201
202
# generate header _t (internal usage) file
open(OUT, ">$target_h_t") || die("Could not open $target_h_t, reason: $!\n");
203
204
205

my $creation_time = localtime(time());

Christian Würdig's avatar
Christian Würdig committed
206
$tmp = uc($arch);
207
208
209

print OUT<<EOF;
/**
Christian Würdig's avatar
Christian Würdig committed
210
 * Generated register classes from spec.
211
212
213
214
215
216
 *
 * DO NOT EDIT THIS FILE, your changes will be lost.
 * Edit $specfile instead.
 * created by: $0 $specfile $target_dir
 * date:       $creation_time
 */
Matthias Braun's avatar
Matthias Braun committed
217
218
219
220
#ifndef _GEN_${tmp}_REGALLOC_IF_T_H_
#define _GEN_${tmp}_REGALLOC_IF_T_H_

#include "gen_${arch}_regalloc_if.h"
221
222
223

EOF

Matthias Braun's avatar
Matthias Braun committed
224
print OUT @obst_header_t;
225

Christian Würdig's avatar
Christian Würdig committed
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
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;
/**
 * 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
 */
Matthias Braun's avatar
Matthias Braun committed
244
245
#ifndef _GEN_${tmp}_REGALLOC_IF_H_
#define _GEN_${tmp}_REGALLOC_IF_H_
Christian Würdig's avatar
Christian Würdig committed
246

247
#include "../bearch.h"
Matthias Braun's avatar
Matthias Braun committed
248
#include "${arch}_nodes_attr.h"
Christian Würdig's avatar
Christian Würdig committed
249
250
251

EOF

252
253
254
255
print OUT @obst_regdef, "\n";

print OUT @obst_classdef, "\n";

256
print OUT @obst_regtypes_decl, "\n";
257
258
259
260
261
262
263

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";

264
265
print OUT "\n#endif /* _GEN_$tmp\_REGALLOC_IF_H_ */\n";

Christian Würdig's avatar
Christian Würdig committed
266
267
close(OUT);

268
269


Christian Würdig's avatar
Christian Würdig committed
270
# generate c file
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
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
 */
Matthias Braun's avatar
Matthias Braun committed
286
#ifdef HAVE_CONFIG_H
287
#include "config.h"
Matthias Braun's avatar
Matthias Braun committed
288
289
#endif

Matthias Braun's avatar
Matthias Braun committed
290
291
292
293
#include "gen_${arch}_regalloc_if.h"
#include "gen_${arch}_machine.h"
#include "bearch_${arch}_t.h"
#include "${arch}_map_regs.h"
294
#include "irmode.h"
295

Matthias Braun's avatar
Matthias Braun committed
296
297
298
299
300
#ifdef BIT
#undef BIT
#endif
#define BIT(x)  (1 << (x % 32))

301
302
EOF

Matthias Braun's avatar
Matthias Braun committed
303
print OUT "arch_register_class_t ${arch}_reg_classes[] = {\n\t".join(",\n\t", @obst_regclasses)."\n};\n\n";
304

305
306
print OUT @obst_regtypes_def, "\n";

Matthias Braun's avatar
Matthias Braun committed
307
print OUT "void ${arch}_register_init(void *isa_ptr) {\n";
308
309
310
311
print OUT @obst_reginit;
print OUT "}\n\n";

print OUT @obst_limit_func;
312

313
314
315
316
print OUT @obst_req;

close(OUT);

317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
###
# 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";
Matthias Braun's avatar
Matthias Braun committed
336
			} elsif (is_reg_class($reqs[$idx])) {
337
				$class = $reqs[$idx];
Matthias Braun's avatar
Matthias Braun committed
338
			} else {
339
340
				my @regs = split(/ /, $reqs[$idx]);
GET_CLASS:		foreach my $reg (@regs) {
341
					if ($reg =~ /!?(in|out)\_r\d+/ || $reg =~ /!in/) {
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
						$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;
}
362

363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
###
# 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;

Matthias Braun's avatar
Matthias Braun committed
379
		my $tmp2 = "const arch_register_req_t ${op}_reg_req_${inout}_${idx} = ";
380
381

		if ($reqs[$idx] eq "none") {
Matthias Braun's avatar
Matthias Braun committed
382
383
384
385
386
387
388
389
390
391
392
			$tmp2 .= "{\n";
			$tmp2 .= "\tarch_register_req_type_none,\n";
			$tmp2 .= "\tNULL,        /* regclass */\n";
			$tmp2 .= "\tNULL,        /* limit bitset */\n";
			$tmp2 .= "\t-1,          /* same pos */\n";
			$tmp2 .= "\t-1           /* different pos */\n";
			$tmp2 .= "};\n";

			push(@obst_req, $tmp2."\n");
			push(@obst_header_t, "extern const arch_register_req_t ${op}_reg_req_${inout}_${idx};\n");
		} elsif ($reqs[$idx] =~ /^new_reg_(.*)$/) {
Christian Würdig's avatar
Christian Würdig committed
393
394
			if (is_reg_class($1)) {
				$tmp2 .= "{\n";
Matthias Braun's avatar
Matthias Braun committed
395
396
397
398
399
				$tmp2 .= "\tarch_register_req_type_should_be_different_from_all,\n";
				$tmp2 .= "\t&${arch}_reg_classes[CLASS_${arch}_$1],\n";
				$tmp2 .= "\tNULL,        /* limit bitset */\n";
				$tmp2 .= "\t-1,          /* same pos */\n";
				$tmp2 .= "\t-1           /* different pos */\n";
Christian Würdig's avatar
Christian Würdig committed
400
401
402
				$tmp2 .= "};\n";

				push(@obst_req, $tmp2."\n");
Matthias Braun's avatar
Matthias Braun committed
403
404
				push(@obst_header_t, "extern const arch_register_req_t ${op}_reg_req_${inout}_${idx};\n");
			} else {
Christian Würdig's avatar
Christian Würdig committed
405
406
				print STDERR "Invalid register class '$1' given in OUT requirement $idx for '$op'.\n";
			}
Matthias Braun's avatar
Matthias Braun committed
407
408
409
410
411
412
413
414
415
416
417
418
419
		} elsif (is_reg_class($reqs[$idx])) {
			my $class = $reqs[$idx];
			$tmp2 .= "{\n";
			$tmp2 .= "\tarch_register_req_type_normal,\n";
			$tmp2 .= "\t&${arch}_reg_classes[CLASS_${arch}_${class}],\n";
			$tmp2 .= "\tNULL,        /* limit bitset */\n";
			$tmp2 .= "\t-1,          /* same pos */\n";
			$tmp2 .= "\t-1           /* different pos */\n";
			$tmp2 .= "};\n";

			push(@obst_req, $tmp2."\n");
			push(@obst_header_t, "extern const arch_register_req_t ${op}_reg_req_${inout}_${idx};\n");
		} else {
420
			my @req_type_mask;
421
422
			my ($class, $has_limit, $same_pos, $different_pos) = build_subset_class_func($n, $op, $idx, (($inout eq "in") ? 1 : 0), $reqs[$idx]);

423
424
425
			if (!defined($class)) {
				die("Could not build subset for ".uc($inout)." requirements '$op' pos $idx ... exiting.\n");
			}
426

427
428
429
			if ($has_limit) {
				push(@req_type_mask, "arch_register_req_type_limited");
			}
430
431
			if (defined($same_pos)) {
				push(@req_type_mask, "arch_register_req_type_should_be_same");
432
			}
433
			if (defined($different_pos)) {
434
435
436
				if ($different_pos == 666) {
					push(@req_type_mask, "arch_register_req_type_should_be_different_from_all");
					undef $different_pos;
Matthias Braun's avatar
Matthias Braun committed
437
				} else {
438
439
					push(@req_type_mask, "arch_register_req_type_should_be_different");
				}
440
441
442
			}

			$tmp2 .= "{\n";
Matthias Braun's avatar
Matthias Braun committed
443
444
445
446
447
			$tmp2 .= "\t".join(" | ", @req_type_mask).",\n";
			$tmp2 .= "\t&${arch}_reg_classes[CLASS_${arch}_${class}],\n";
			$tmp2 .= "\t".($has_limit ? "limit_reg_${op}_${inout}_${idx}" : "NULL").",\n";
			$tmp2 .= "\t".(defined($same_pos) ? $same_pos : "-1").",\n";
			$tmp2 .= "\t".(defined($different_pos) ? $different_pos : "-1")."\n";
448
			$tmp2 .= "};\n";
449

450
			push(@obst_req, $tmp2."\n");
Matthias Braun's avatar
Matthias Braun committed
451
			push(@obst_header_t, "extern const arch_register_req_t ${op}_reg_req_${inout}_${idx};\n");
452
453
454
455
		}
	}

}
456
457
458
459
460
461

###
# Determines whether $name is a specified register class or not.
# @return 1 if name is register class, 0 otherwise
###
sub is_reg_class {
462
463
464
	my $name = shift;
	return 1 if exists($reg_classes{"$name"});
	return 0;
465
466
467
468
469
470
471
}

###
# Returns the register class for a given register.
# @return class or undef
###
sub get_reg_class {
472
	my $reg = shift;
473
	$reg = substr($reg, 1) if ($reg =~ /!.*/);
474
475
	return $reg2class{"$reg"}{"class"} if (exists($reg2class{"$reg"}));
	return undef;
476
477
478
479
480
481
482
}

###
# Returns the index of a given register within it's register class.
# @return index or undef
###
sub get_reg_index {
483
484
485
	my $reg = shift;
	return $reg2class{"$reg"}{"index"} if (exists($reg2class{"$reg"}));
	return undef;
486
487
488
489
490
}

###
# Generates the function for a given $op and a given IN-index
# which returns a subset of possible register from a register class
491
492
# @return classname from which the subset is derived or undef and
#         pos which corresponds to in/out reference position or undef
493
494
###
sub build_subset_class_func {
495
496
497
498
499
	my $neg           = undef;
	my $class         = undef;
	my $has_limit     = 0;
	my $same_pos      = undef;
	my $different_pos = undef;
500
	my $temp;
501
502
503
	my @obst_init;
	my @obst_limits;
	my @obst_ignore;
Matthias Braun's avatar
Matthias Braun committed
504
	my @limit_array;
505

506
507
508
509
510
	# build function header
	my $n   = shift;
	my $op  = shift;
	my $idx = shift;
	my $in  = shift;
511
512
513
514
515
516
517
518
519

	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+)/) {
520
			if (($1 && defined($different_pos)) || (!$1 && defined($same_pos))) {
521
				print STDERR "Multiple in/out references of same type in one requirement not allowed.\n";
522
523
				return (undef, undef, undef, undef);
			}
524
525
526
527
528
529
530
531

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

532
533
534
			$class = $idx_class[$2 - 1];
			next CHECK_REQS;
		}
535
536
537
538
		elsif (/!in/) {
			$class = $idx_class[0];
			return ($class, 0, undef, 666);
		}
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554

		# 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;
Matthias Braun's avatar
Matthias Braun committed
555
		} else {
556
557
558
559
560
561
562
			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);
			}

Matthias Braun's avatar
Matthias Braun committed
563
			$has_limit = 1;
564
565
566
567
568
569
570
571
572
573
574
575
576
			$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;
Matthias Braun's avatar
Matthias Braun committed
577
		} elsif ($class ne $temp) {
578
579
580
581
582
			# all registers must belong to the same class
			print STDERR "Registerclass mismatch. '$_' is not member of class '$class'.\n";
			return (undef, undef, undef, undef);
		}

Matthias Braun's avatar
Matthias Braun committed
583
584
585
586
587
		# calculate position inside the initializer bitfield (only 32 bits per
		# element)
		my $regidx = get_reg_index($_);
		my $arrayp = $regidx / 32;
		push(@{$limit_array[$arrayp]}, $_);
588
589
	}

Matthias Braun's avatar
Matthias Braun committed
590
591
592
593
594
595
596
597
598
599
	# 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);
			}
600
601
602
		}
	}

603
	if ($has_limit == 1) {
604
		push(@obst_limit_func, "static const unsigned limit_reg_${op}_".($in ? "in" : "out")."_". ${idx} ."[] = { ");
Matthias Braun's avatar
Matthias Braun committed
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
		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");
634
635
	}

636
	return ($class, $has_limit, $same_pos, $different_pos);
637
}
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667

###
# 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;
}