Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright 2012 Advanced Micro Devices, Inc.
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * on the rights to use, copy, modify, merge, publish, distribute, sub
  8.  * license, and/or sell copies of the Software, and to permit persons to whom
  9.  * the Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  18.  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  19.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  20.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  21.  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  22.  *
  23.  * Author: Tom Stellard <thomas.stellard@amd.com>
  24.  */
  25.  
  26. #include "radeon_compiler.h"
  27. #include "radeon_compiler_util.h"
  28. #include "radeon_dataflow.h"
  29. #include "radeon_program.h"
  30. #include "radeon_program_constants.h"
  31. #include <stdio.h>
  32.  
  33. #define VERBOSE 0
  34.  
  35. #define DBG(...) do { if (VERBOSE) fprintf(stderr, __VA_ARGS__); } while(0)
  36.  
  37. /* IEEE-754:
  38.  * 22:0 mantissa
  39.  * 30:23 exponent
  40.  * 31 sign
  41.  *
  42.  * R300:
  43.  * 0:2 mantissa
  44.  * 3:6 exponent (bias 7)
  45.  */
  46. static int ieee_754_to_r300_float(float f, unsigned char *r300_float_out)
  47. {
  48.         unsigned float_bits = *((unsigned *)&f);
  49.         /* XXX: Handle big-endian */
  50.         unsigned mantissa = float_bits &         0x007fffff;
  51.         unsigned biased_exponent = (float_bits & 0x7f800000) >> 23;
  52.         unsigned negate = !!(float_bits &         0x80000000);
  53.         int exponent = biased_exponent - 127;
  54.         unsigned mantissa_mask = 0xff8fffff;
  55.         unsigned r300_exponent, r300_mantissa;
  56.  
  57.         DBG("Converting %f (0x%x) to 7-bit:\n", f, float_bits);
  58.         DBG("Raw exponent = %d\n", exponent);
  59.  
  60.         if (exponent < -7 || exponent > 8) {
  61.                 DBG("Failed exponent out of range\n\n");
  62.                 return 0;
  63.         }
  64.  
  65.         if (mantissa & mantissa_mask) {
  66.                 DBG("Failed mantisa has too many bits:\n"
  67.                         "manitssa=0x%x mantissa_mask=0x%x, and=0x%x\n\n",
  68.                         mantissa, mantissa_mask,
  69.                         mantissa & mantissa_mask);
  70.                 return 0;
  71.         }
  72.  
  73.         r300_exponent = exponent + 7;
  74.         r300_mantissa = (mantissa & ~mantissa_mask) >> 20;
  75.         *r300_float_out = r300_mantissa | (r300_exponent << 3);
  76.  
  77.         DBG("Success! r300_float = 0x%x\n\n", *r300_float_out);
  78.  
  79.         if (negate)
  80.                 return -1;
  81.         else
  82.                 return 1;
  83. }
  84.  
  85. void rc_inline_literals(struct radeon_compiler *c, void *user)
  86. {
  87.         struct rc_instruction * inst;
  88.  
  89.         for(inst = c->Program.Instructions.Next;
  90.                                         inst != &c->Program.Instructions;
  91.                                         inst = inst->Next) {
  92.                 const struct rc_opcode_info * info =
  93.                                         rc_get_opcode_info(inst->U.I.Opcode);
  94.  
  95.                 unsigned src_idx;
  96.                 struct rc_constant * constant;
  97.                 float float_value;
  98.                 unsigned char r300_float = 0;
  99.                 int ret;
  100.  
  101.                 /* XXX: Handle presub */
  102.  
  103.                 /* We aren't using rc_for_all_reads_src here, because presub
  104.                  * sources need to be handled differently. */
  105.                 for (src_idx = 0; src_idx < info->NumSrcRegs; src_idx++) {
  106.                         unsigned new_swizzle;
  107.                         unsigned use_literal = 0;
  108.                         unsigned negate_mask = 0;
  109.                         unsigned swz, chan;
  110.                         struct rc_src_register * src_reg =
  111.                                                 &inst->U.I.SrcReg[src_idx];
  112.                         swz = RC_SWIZZLE_UNUSED;
  113.                         if (src_reg->File != RC_FILE_CONSTANT) {
  114.                                 continue;
  115.                         }
  116.                         constant =
  117.                                 &c->Program.Constants.Constants[src_reg->Index];
  118.                         if (constant->Type != RC_CONSTANT_IMMEDIATE) {
  119.                                 continue;
  120.                         }
  121.                         new_swizzle = rc_init_swizzle(RC_SWIZZLE_UNUSED, 0);
  122.                         for (chan = 0; chan < 4; chan++) {
  123.                                 unsigned char r300_float_tmp;
  124.                                 swz = GET_SWZ(src_reg->Swizzle, chan);
  125.                                 if (swz == RC_SWIZZLE_UNUSED) {
  126.                                         continue;
  127.                                 }
  128.                                 float_value = constant->u.Immediate[swz];
  129.                                 ret = ieee_754_to_r300_float(float_value,
  130.                                                                 &r300_float_tmp);
  131.                                 if (!ret || (use_literal &&
  132.                                                 r300_float != r300_float_tmp)) {
  133.                                         use_literal = 0;
  134.                                         break;
  135.                                 }
  136.  
  137.                                 if (ret == -1 && src_reg->Abs) {
  138.                                         use_literal = 0;
  139.                                         break;
  140.                                 }
  141.  
  142.                                 if (!use_literal) {
  143.                                         r300_float = r300_float_tmp;
  144.                                         use_literal = 1;
  145.                                 }
  146.  
  147.                                 /* Use RC_SWIZZLE_W for the inline constant, so
  148.                                  * it will become one of the alpha sources. */
  149.                                 SET_SWZ(new_swizzle, chan, RC_SWIZZLE_W);
  150.                                 if (ret == -1) {
  151.                                         negate_mask |= (1 << chan);
  152.                                 }
  153.                         }
  154.  
  155.                         if (!use_literal) {
  156.                                 continue;
  157.                         }
  158.                         src_reg->File = RC_FILE_INLINE;
  159.                         src_reg->Index = r300_float;
  160.                         src_reg->Swizzle = new_swizzle;
  161.                         src_reg->Negate = src_reg->Negate ^ negate_mask;
  162.                 }
  163.         }
  164. }
  165.