radeon/llvm: do not convert f32 operand of select_cc node
[mesa.git] / src / gallium / drivers / radeon / R600GenRegisterInfo.pl
1 #===-- R600GenRegisterInfo.pl - Script for generating register info files --===#
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 # This perl script prints to stdout .td code to be used as R600RegisterInfo.td
11 # it also generates a file called R600HwRegInfo.include, which contains helper
12 # functions for determining the hw encoding of registers.
13 #
14 #===------------------------------------------------------------------------===#
15
16 use strict;
17 use warnings;
18
19 use constant CONST_REG_COUNT => 1024;
20 use constant TEMP_REG_COUNT => 128;
21
22 my $CREG_MAX = CONST_REG_COUNT - 1;
23 my $TREG_MAX = TEMP_REG_COUNT - 1;
24
25 print <<STRING;
26
27 class R600Reg <string name> : Register<name> {
28 let Namespace = "AMDGPU";
29 }
30
31 class R600Reg_128<string n, list<Register> subregs> : RegisterWithSubRegs<n, subregs> {
32 let Namespace = "AMDGPU";
33 let SubRegIndices = [sel_x, sel_y, sel_z, sel_w];
34 }
35
36 STRING
37
38 my $i;
39
40 ### REG DEFS ###
41
42 my @creg_list = print_reg_defs(CONST_REG_COUNT * 4, "C");
43 my @treg_list = print_reg_defs(TEMP_REG_COUNT * 4, "T");
44
45 my @t128reg;
46 my @treg_x;
47 for (my $i = 0; $i < TEMP_REG_COUNT; $i++) {
48 my $name = "T$i\_XYZW";
49 print qq{def $name : R600Reg_128 <"T$i.XYZW", [T$i\_X, T$i\_Y, T$i\_Z, T$i\_W] >;\n};
50 $t128reg[$i] = $name;
51 $treg_x[$i] = "T$i\_X";
52 }
53
54 my $treg_string = join(",", @treg_list);
55 my $creg_list = join(",", @creg_list);
56 my $t128_string = join(",", @t128reg);
57 my $treg_x_string = join(",", @treg_x);
58 print <<STRING;
59
60 class RegSet <dag s> {
61 dag set = s;
62 }
63
64 def ZERO : R600Reg<"0.0">;
65 def HALF : R600Reg<"0.5">;
66 def ONE : R600Reg<"1.0">;
67 def ONE_INT : R600Reg<"1">;
68 def NEG_HALF : R600Reg<"-0.5">;
69 def NEG_ONE : R600Reg<"-1.0">;
70 def PV_X : R600Reg<"pv.x">;
71 def ALU_LITERAL_X : R600Reg<"literal.x">;
72 def PREDICATE_BIT : R600Reg<"PredicateBit">;
73 def PRED_SEL_OFF: R600Reg<"Pred_sel_off">;
74 def PRED_SEL_ZERO : R600Reg<"Pred_sel_zero">;
75 def PRED_SEL_ONE : R600Reg<"Pred_sel_one">;
76
77 def R600_CReg32 : RegisterClass <"AMDGPU", [f32, i32], 32, (add
78 $creg_list)>;
79
80 def R600_TReg32 : RegisterClass <"AMDGPU", [f32, i32], 32, (add
81 $treg_string)>;
82
83 def R600_TReg32_X : RegisterClass <"AMDGPU", [f32, i32], 32, (add
84 $treg_x_string)>;
85
86 def R600_Reg32 : RegisterClass <"AMDGPU", [f32, i32], 32, (add
87 R600_TReg32,
88 R600_CReg32,
89 ZERO, HALF, ONE, ONE_INT, PV_X, ALU_LITERAL_X, NEG_ONE, NEG_HALF)>;
90
91 def R600_Predicate : RegisterClass <"AMDGPU", [i32], 32, (add
92 PRED_SEL_OFF, PRED_SEL_ZERO, PRED_SEL_ONE)>;
93
94 def R600_Predicate_Bit: RegisterClass <"AMDGPU", [i32], 32, (add
95 PREDICATE_BIT)>;
96
97 def R600_Reg128 : RegisterClass<"AMDGPU", [v4f32, v4i32], 128, (add
98 $t128_string)>
99 {
100 let SubRegClasses = [(R600_TReg32 sel_x, sel_y, sel_z, sel_w)];
101 let CopyCost = -1;
102 }
103
104 STRING
105
106 my %index_map;
107 my %chan_map;
108
109 for ($i = 0; $i <= $#creg_list; $i++) {
110 push(@{$index_map{get_hw_index($i)}}, $creg_list[$i]);
111 push(@{$chan_map{get_chan_str($i)}}, $creg_list[$i]);
112 }
113
114 for ($i = 0; $i <= $#treg_list; $i++) {
115 push(@{$index_map{get_hw_index($i)}}, $treg_list[$i]);
116 push(@{$chan_map{get_chan_str($i)}}, $treg_list[$i]);
117 }
118
119 for ($i = 0; $i <= $#t128reg; $i++) {
120 push(@{$index_map{$i}}, $t128reg[$i]);
121 push(@{$chan_map{'X'}}, $t128reg[$i]);
122 }
123
124 open(OUTFILE, ">", "R600HwRegInfo.include");
125
126 print OUTFILE <<STRING;
127
128 unsigned R600RegisterInfo::getHWRegIndexGen(unsigned reg) const
129 {
130 switch(reg) {
131 default: assert(!"Unknown register"); return 0;
132 STRING
133 foreach my $key (keys(%index_map)) {
134 foreach my $reg (@{$index_map{$key}}) {
135 print OUTFILE " case AMDGPU::$reg:\n";
136 }
137 print OUTFILE " return $key;\n\n";
138 }
139
140 print OUTFILE " }\n}\n\n";
141
142 print OUTFILE <<STRING;
143
144 unsigned R600RegisterInfo::getHWRegChanGen(unsigned reg) const
145 {
146 switch(reg) {
147 default: assert(!"Unknown register"); return 0;
148 STRING
149
150 foreach my $key (keys(%chan_map)) {
151 foreach my $reg (@{$chan_map{$key}}) {
152 print OUTFILE " case AMDGPU::$reg:\n";
153 }
154 my $val;
155 if ($key eq 'X') {
156 $val = 0;
157 } elsif ($key eq 'Y') {
158 $val = 1;
159 } elsif ($key eq 'Z') {
160 $val = 2;
161 } elsif ($key eq 'W') {
162 $val = 3;
163 } else {
164 die("Unknown chan value; $key");
165 }
166 print OUTFILE " return $val;\n\n";
167 }
168
169 print OUTFILE " }\n}\n\n";
170
171 sub print_reg_defs {
172 my ($count, $prefix) = @_;
173
174 my @reg_list;
175
176 for ($i = 0; $i < $count; $i++) {
177 my $hw_index = get_hw_index($i);
178 my $chan= get_chan_str($i);
179 my $name = "$prefix$hw_index\_$chan";
180 print qq{def $name : R600Reg <"$prefix$hw_index.$chan">;\n};
181 $reg_list[$i] = $name;
182 }
183 return @reg_list;
184 }
185
186 #Helper functions
187 sub get_hw_index {
188 my ($index) = @_;
189 return int($index / 4);
190 }
191
192 sub get_chan_str {
193 my ($index) = @_;
194 my $chan = $index % 4;
195 if ($chan == 0 ) {
196 return 'X';
197 } elsif ($chan == 1) {
198 return 'Y';
199 } elsif ($chan == 2) {
200 return 'Z';
201 } elsif ($chan == 3) {
202 return 'W';
203 } else {
204 die("Unknown chan value: $chan");
205 }
206 }