Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (C) 2008 Nicolai Haehnle.
  3.  *
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining
  7.  * a copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sublicense, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial
  16.  * portions of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  21.  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
  22.  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  23.  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  24.  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  */
  27.  
  28. #include "radeon_program.h"
  29.  
  30. #include <stdio.h>
  31.  
  32. #include "radeon_compiler.h"
  33. #include "radeon_dataflow.h"
  34.  
  35.  
  36. /**
  37.  * Transform the given clause in the following way:
  38.  *  1. Replace it with an empty clause
  39.  *  2. For every instruction in the original clause, try the given
  40.  *     transformations in order.
  41.  *  3. If one of the transformations returns GL_TRUE, assume that it
  42.  *     has emitted the appropriate instruction(s) into the new clause;
  43.  *     otherwise, copy the instruction verbatim.
  44.  *
  45.  * \note The transformation is currently not recursive; in other words,
  46.  * instructions emitted by transformations are not transformed.
  47.  *
  48.  * \note The transform is called 'local' because it can only look at
  49.  * one instruction at a time.
  50.  */
  51. void rc_local_transform(
  52.         struct radeon_compiler * c,
  53.         void *user)
  54. {
  55.         struct radeon_program_transformation *transformations =
  56.                 (struct radeon_program_transformation*)user;
  57.         struct rc_instruction * inst = c->Program.Instructions.Next;
  58.  
  59.         while(inst != &c->Program.Instructions) {
  60.                 struct rc_instruction * current = inst;
  61.                 int i;
  62.  
  63.                 inst = inst->Next;
  64.  
  65.                 for(i = 0; transformations[i].function; ++i) {
  66.                         struct radeon_program_transformation* t = transformations + i;
  67.  
  68.                         if (t->function(c, current, t->userData))
  69.                                 break;
  70.                 }
  71.         }
  72. }
  73.  
  74. struct get_used_temporaries_data {
  75.         unsigned char * Used;
  76.         unsigned int UsedLength;
  77. };
  78.  
  79. static void get_used_temporaries_cb(
  80.         void * userdata,
  81.         struct rc_instruction * inst,
  82.         rc_register_file file,
  83.         unsigned int index,
  84.         unsigned int mask)
  85. {
  86.         struct get_used_temporaries_data * d = userdata;
  87.  
  88.         if (file != RC_FILE_TEMPORARY)
  89.                 return;
  90.  
  91.         if (index >= d->UsedLength)
  92.                 return;
  93.  
  94.         d->Used[index] |= mask;
  95. }
  96.  
  97. /**
  98.  * This function fills in the parameter 'used' with a writemask that
  99.  * represent which components of each temporary register are used by the
  100.  * program.  This is meant to be combined with rc_find_free_temporary_list as a
  101.  * more efficient version of rc_find_free_temporary.
  102.  * @param used The function does not initialize this parameter.
  103.  */
  104. void rc_get_used_temporaries(
  105.         struct radeon_compiler * c,
  106.         unsigned char * used,
  107.         unsigned int used_length)
  108. {
  109.         struct rc_instruction * inst;
  110.         struct get_used_temporaries_data d;
  111.         d.Used = used;
  112.         d.UsedLength = used_length;
  113.  
  114.         for(inst = c->Program.Instructions.Next;
  115.                         inst != &c->Program.Instructions; inst = inst->Next) {
  116.  
  117.                 rc_for_all_reads_mask(inst, get_used_temporaries_cb, &d);
  118.                 rc_for_all_writes_mask(inst, get_used_temporaries_cb, &d);
  119.         }
  120. }
  121.  
  122. /* Search a list of used temporaries for a free one
  123.  * \sa rc_get_used_temporaries
  124.  * @note If this functions finds a free temporary, it will mark it as used
  125.  * in the used temporary list (param 'used')
  126.  * @param used list of used temporaries
  127.  * @param used_length number of items in param 'used'
  128.  * @param mask which components must be free in the temporary index that is
  129.  * returned.
  130.  * @return -1 If there are no more free temporaries, otherwise the index of
  131.  * a temporary register where the components specified in param 'mask' are
  132.  * not being used.
  133.  */
  134. int rc_find_free_temporary_list(
  135.         struct radeon_compiler * c,
  136.         unsigned char * used,
  137.         unsigned int used_length,
  138.         unsigned int mask)
  139. {
  140.         int i;
  141.         for(i = 0; i < used_length; i++) {
  142.                 if ((~used[i] & mask) == mask) {
  143.                         used[i] |= mask;
  144.                         return i;
  145.                 }
  146.         }
  147.         return -1;
  148. }
  149.  
  150. unsigned int rc_find_free_temporary(struct radeon_compiler * c)
  151. {
  152.         unsigned char used[RC_REGISTER_MAX_INDEX];
  153.         int free;
  154.  
  155.         memset(used, 0, sizeof(used));
  156.  
  157.         rc_get_used_temporaries(c, used, RC_REGISTER_MAX_INDEX);
  158.  
  159.         free = rc_find_free_temporary_list(c, used, RC_REGISTER_MAX_INDEX,
  160.                                                                 RC_MASK_XYZW);
  161.         if (free < 0) {
  162.                 rc_error(c, "Ran out of temporary registers\n");
  163.                 return 0;
  164.         }
  165.         return free;
  166. }
  167.  
  168.  
  169. struct rc_instruction *rc_alloc_instruction(struct radeon_compiler * c)
  170. {
  171.         struct rc_instruction * inst = memory_pool_malloc(&c->Pool, sizeof(struct rc_instruction));
  172.  
  173.         memset(inst, 0, sizeof(struct rc_instruction));
  174.  
  175.         inst->U.I.Opcode = RC_OPCODE_ILLEGAL_OPCODE;
  176.         inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
  177.         inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
  178.         inst->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_XYZW;
  179.         inst->U.I.SrcReg[2].Swizzle = RC_SWIZZLE_XYZW;
  180.  
  181.         return inst;
  182. }
  183.  
  184. void rc_insert_instruction(struct rc_instruction * after, struct rc_instruction * inst)
  185. {
  186.         inst->Prev = after;
  187.         inst->Next = after->Next;
  188.  
  189.         inst->Prev->Next = inst;
  190.         inst->Next->Prev = inst;
  191. }
  192.  
  193. struct rc_instruction *rc_insert_new_instruction(struct radeon_compiler * c, struct rc_instruction * after)
  194. {
  195.         struct rc_instruction * inst = rc_alloc_instruction(c);
  196.  
  197.         rc_insert_instruction(after, inst);
  198.  
  199.         return inst;
  200. }
  201.  
  202. void rc_remove_instruction(struct rc_instruction * inst)
  203. {
  204.         inst->Prev->Next = inst->Next;
  205.         inst->Next->Prev = inst->Prev;
  206. }
  207.  
  208. /**
  209.  * Return the number of instructions in the program.
  210.  */
  211. unsigned int rc_recompute_ips(struct radeon_compiler * c)
  212. {
  213.         unsigned int ip = 0;
  214.         struct rc_instruction * inst;
  215.  
  216.         for(inst = c->Program.Instructions.Next;
  217.             inst != &c->Program.Instructions;
  218.             inst = inst->Next) {
  219.                 inst->IP = ip++;
  220.         }
  221.  
  222.         c->Program.Instructions.IP = 0xcafedead;
  223.  
  224.         return ip;
  225. }
  226.