Path: blob/21.2-virgl/src/gallium/drivers/r300/compiler/radeon_inline_literals.c
4574 views
/*1* Copyright 2012 Advanced Micro Devices, Inc.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* on the rights to use, copy, modify, merge, publish, distribute, sub7* license, and/or sell copies of the Software, and to permit persons to whom8* the Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,18* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR19* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE20* USE OR OTHER DEALINGS IN THE SOFTWARE.21*22* Author: Tom Stellard <[email protected]>23*/2425#include "radeon_compiler.h"26#include "radeon_compiler_util.h"27#include "radeon_dataflow.h"28#include "radeon_program.h"29#include "radeon_program_constants.h"30#include "util/u_bitcast.h"31#include <stdio.h>3233#define VERBOSE 03435#define DBG(...) do { if (VERBOSE) fprintf(stderr, __VA_ARGS__); } while(0)3637/* IEEE-754:38* 22:0 mantissa39* 30:23 exponent40* 31 sign41*42* R300:43* 0:2 mantissa44* 3:6 exponent (bias 7)45*/46static int ieee_754_to_r300_float(float f, unsigned char *r300_float_out)47{48unsigned float_bits = u_bitcast_f2u(f);49/* XXX: Handle big-endian */50unsigned mantissa = float_bits & 0x007fffff;51unsigned biased_exponent = (float_bits & 0x7f800000) >> 23;52unsigned negate = !!(float_bits & 0x80000000);53int exponent = biased_exponent - 127;54unsigned mantissa_mask = 0xff8fffff;55unsigned r300_exponent, r300_mantissa;5657DBG("Converting %f (0x%x) to 7-bit:\n", f, float_bits);58DBG("Raw exponent = %d\n", exponent);5960if (exponent < -7 || exponent > 8) {61DBG("Failed exponent out of range\n\n");62return 0;63}6465if (mantissa & mantissa_mask) {66DBG("Failed mantissa has too many bits:\n"67"mantissa=0x%x mantissa_mask=0x%x, and=0x%x\n\n",68mantissa, mantissa_mask,69mantissa & mantissa_mask);70return 0;71}7273r300_exponent = exponent + 7;74r300_mantissa = (mantissa & ~mantissa_mask) >> 20;75*r300_float_out = r300_mantissa | (r300_exponent << 3);7677DBG("Success! r300_float = 0x%x\n\n", *r300_float_out);7879if (negate)80return -1;81else82return 1;83}8485void rc_inline_literals(struct radeon_compiler *c, void *user)86{87struct rc_instruction * inst;8889for(inst = c->Program.Instructions.Next;90inst != &c->Program.Instructions;91inst = inst->Next) {92const struct rc_opcode_info * info =93rc_get_opcode_info(inst->U.I.Opcode);9495unsigned src_idx;96struct rc_constant * constant;97float float_value;98unsigned char r300_float = 0;99int ret;100101/* XXX: Handle presub */102103/* We aren't using rc_for_all_reads_src here, because presub104* sources need to be handled differently. */105for (src_idx = 0; src_idx < info->NumSrcRegs; src_idx++) {106unsigned new_swizzle;107unsigned use_literal = 0;108unsigned negate_mask = 0;109unsigned swz, chan;110struct rc_src_register * src_reg =111&inst->U.I.SrcReg[src_idx];112swz = RC_SWIZZLE_UNUSED;113if (src_reg->File != RC_FILE_CONSTANT) {114continue;115}116constant =117&c->Program.Constants.Constants[src_reg->Index];118if (constant->Type != RC_CONSTANT_IMMEDIATE) {119continue;120}121new_swizzle = rc_init_swizzle(RC_SWIZZLE_UNUSED, 0);122for (chan = 0; chan < 4; chan++) {123unsigned char r300_float_tmp;124swz = GET_SWZ(src_reg->Swizzle, chan);125if (swz == RC_SWIZZLE_UNUSED) {126continue;127}128float_value = constant->u.Immediate[swz];129ret = ieee_754_to_r300_float(float_value,130&r300_float_tmp);131if (!ret || (use_literal &&132r300_float != r300_float_tmp)) {133use_literal = 0;134break;135}136137if (ret == -1 && src_reg->Abs) {138use_literal = 0;139break;140}141142if (!use_literal) {143r300_float = r300_float_tmp;144use_literal = 1;145}146147/* Use RC_SWIZZLE_W for the inline constant, so148* it will become one of the alpha sources. */149SET_SWZ(new_swizzle, chan, RC_SWIZZLE_W);150if (ret == -1) {151negate_mask |= (1 << chan);152}153}154155if (!use_literal) {156continue;157}158src_reg->File = RC_FILE_INLINE;159src_reg->Index = r300_float;160src_reg->Swizzle = new_swizzle;161src_reg->Negate = src_reg->Negate ^ negate_mask;162}163}164}165166167