Home | History | Annotate | Download | only in radeon
      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