R600GenRegisterInfo.pl revision 788fd04dacb9eb1e32010050c57cd2f49779311b
1#===-- R600GenRegisterInfo.pl - TODO: Add brief description -------===#
2#
3#                     The LLVM Compiler Infrastructure
4#
5# This file is distributed under the University of Illinois Open Source
6# License. See LICENSE.TXT for details.
7#
8#===----------------------------------------------------------------------===#
9#
10# TODO: Add full description
11#
12#===----------------------------------------------------------------------===#
13
14use strict;
15use warnings;
16
17use constant CONST_REG_COUNT => 256;
18use constant TEMP_REG_COUNT => 128;
19
20my $CREG_MAX = CONST_REG_COUNT - 1;
21my $TREG_MAX = TEMP_REG_COUNT - 1;
22
23print <<STRING;
24
25class R600Reg <string name> : Register<name> {
26  let Namespace = "AMDIL";
27}
28
29class R600Reg_128<string n, list<Register> subregs> : RegisterWithSubRegs<n, subregs> {
30  let Namespace = "AMDIL";
31  let SubRegIndices = [sel_x, sel_y, sel_z, sel_w];
32}
33
34STRING
35
36my $i;
37
38### REG DEFS ###
39
40my @creg_list = print_reg_defs(CONST_REG_COUNT * 4, "C");
41my @treg_list = print_reg_defs(TEMP_REG_COUNT * 4, "T");
42
43my @t128reg;
44my @treg_x;
45for (my $i = 0; $i < TEMP_REG_COUNT; $i++) {
46  my $name = "T$i\_XYZW";
47  print qq{def $name : R600Reg_128 <"T$i.XYZW", [T$i\_X, T$i\_Y, T$i\_Z, T$i\_W] >;\n};
48  $t128reg[$i] = $name;
49  $treg_x[$i] = "T$i\_X";
50}
51
52my $treg_string = join(",", @treg_list);
53my $creg_list = join(",", @creg_list);
54my $t128_string = join(",", @t128reg);
55my $treg_x_string = join(",", @treg_x);
56print <<STRING;
57
58class RegSet <dag s> {
59  dag set = s;
60}
61
62def ZERO : R600Reg<"0.0">;
63def HALF : R600Reg<"0.5">;
64def ONE : R600Reg<"1.0">;
65def ONE_INT : R600Reg<"1">;
66def NEG_HALF : R600Reg<"-0.5">;
67def NEG_ONE : R600Reg<"-1.0">;
68def PV_X : R600Reg<"pv.x">;
69def ALU_LITERAL_X : R600Reg<"literal.x">;
70
71def R600_CReg32 : RegisterClass <"AMDIL", [f32, i32], 32, (add
72    $creg_list)>;
73
74def R600_TReg32 : RegisterClass <"AMDIL", [f32, i32], 32, (add
75    $treg_string)>;
76
77def R600_TReg32_X : RegisterClass <"AMDIL", [f32, i32], 32, (add
78    $treg_x_string)>;
79
80def R600_Reg32 : RegisterClass <"AMDIL", [f32, i32], 32, (add
81    R600_TReg32,
82    R600_CReg32,
83    ZERO, HALF, ONE, ONE_INT, PV_X, ALU_LITERAL_X, NEG_ONE, NEG_HALF)>;
84
85def R600_Reg128 : RegisterClass<"AMDIL", [v4f32, v4i32], 128, (add
86    $t128_string)>
87{
88  let SubRegClasses = [(R600_TReg32 sel_x, sel_y, sel_z, sel_w)];
89  let CopyCost = -1;
90}
91
92STRING
93
94my %index_map;
95my %chan_map;
96
97for ($i = 0; $i <= $#creg_list; $i++) {
98  push(@{$index_map{get_hw_index($i)}}, $creg_list[$i]);
99  push(@{$chan_map{get_chan_str($i)}}, $creg_list[$i]);
100}
101
102for ($i = 0; $i <= $#treg_list; $i++) {
103  push(@{$index_map{get_hw_index($i)}}, $treg_list[$i]);
104  push(@{$chan_map{get_chan_str($i)}}, $treg_list[$i]);
105}
106
107for ($i = 0; $i <= $#t128reg; $i++) {
108  push(@{$index_map{$i}}, $t128reg[$i]);
109  push(@{$chan_map{'X'}}, $t128reg[$i]);
110}
111
112open(OUTFILE, ">", "R600HwRegInfo.include");
113
114print OUTFILE <<STRING;
115
116unsigned R600RegisterInfo::getHWRegIndexGen(unsigned reg) const
117{
118  switch(reg) {
119  default: assert(!"Unknown register"); return 0;
120STRING
121foreach my $key (keys(%index_map)) {
122  foreach my $reg (@{$index_map{$key}}) {
123    print OUTFILE "  case AMDIL::$reg:\n";
124  }
125  print OUTFILE "    return $key;\n\n";
126}
127
128print OUTFILE "  }\n}\n\n";
129
130print OUTFILE <<STRING;
131
132unsigned R600RegisterInfo::getHWRegChanGen(unsigned reg) const
133{
134  switch(reg) {
135  default: assert(!"Unknown register"); return 0;
136STRING
137
138foreach my $key (keys(%chan_map)) {
139  foreach my $reg (@{$chan_map{$key}}) {
140    print OUTFILE " case AMDIL::$reg:\n";
141  }
142  my $val;
143  if ($key eq 'X') {
144    $val = 0;
145  } elsif ($key eq 'Y') {
146    $val = 1;
147  } elsif ($key eq 'Z') {
148    $val = 2;
149  } elsif ($key eq 'W') {
150    $val = 3;
151  } else {
152    die("Unknown chan value; $key");
153  }
154  print OUTFILE "    return $val;\n\n";
155}
156
157print OUTFILE "  }\n}\n\n";
158
159sub print_reg_defs {
160  my ($count, $prefix) = @_;
161
162  my @reg_list;
163
164  for ($i = 0; $i < $count; $i++) {
165    my $hw_index = get_hw_index($i);
166    my $chan= get_chan_str($i);
167    my $name = "$prefix$hw_index\_$chan";
168    print qq{def $name : R600Reg <"$prefix$hw_index.$chan">;\n};
169    $reg_list[$i] = $name;
170  }
171  return @reg_list;
172}
173
174#Helper functions
175sub get_hw_index {
176  my ($index) = @_;
177  return int($index / 4);
178}
179
180sub get_chan_str {
181  my ($index) = @_;
182  my $chan = $index % 4;
183  if ($chan == 0 )  {
184    return 'X';
185  } elsif ($chan == 1) {
186    return 'Y';
187  } elsif ($chan == 2) {
188    return 'Z';
189  } elsif ($chan == 3) {
190    return 'W';
191  } else {
192    die("Unknown chan value: $chan");
193  }
194}
195