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 } 207