• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "radeon_swizzle.h"
32 #include "util/u_bitcast.h"
33 #include <stdio.h>
34 
35 #define VERBOSE 0
36 
37 #define DBG(...) do { if (VERBOSE) fprintf(stderr, __VA_ARGS__); } while(0)
38 
39 /* IEEE-754:
40  * 22:0 mantissa
41  * 30:23 exponent
42  * 31 sign
43  *
44  * R300:
45  * 0:2 mantissa
46  * 3:6 exponent (bias 7)
47  */
ieee_754_to_r300_float(float f,unsigned char * r300_float_out)48 static int ieee_754_to_r300_float(float f, unsigned char *r300_float_out)
49 {
50 	unsigned float_bits = u_bitcast_f2u(f);
51 	/* XXX: Handle big-endian */
52 	unsigned mantissa = float_bits &         0x007fffff;
53 	unsigned biased_exponent = (float_bits & 0x7f800000) >> 23;
54 	unsigned negate = !!(float_bits &         0x80000000);
55 	int exponent = biased_exponent - 127;
56 	unsigned mantissa_mask = 0xff8fffff;
57 	unsigned r300_exponent, r300_mantissa;
58 
59 	DBG("Converting %f (0x%x) to 7-bit:\n", f, float_bits);
60 	DBG("Raw exponent = %d\n", exponent);
61 
62 	if (exponent < -7 || exponent > 8) {
63 		DBG("Failed exponent out of range\n\n");
64 		return 0;
65 	}
66 
67 	if (mantissa & mantissa_mask) {
68 		DBG("Failed mantissa has too many bits:\n"
69 			"mantissa=0x%x mantissa_mask=0x%x, and=0x%x\n\n",
70 			mantissa, mantissa_mask,
71 			mantissa & mantissa_mask);
72 		return 0;
73 	}
74 
75 	r300_exponent = exponent + 7;
76 	r300_mantissa = (mantissa & ~mantissa_mask) >> 20;
77 	*r300_float_out = r300_mantissa | (r300_exponent << 3);
78 
79 	DBG("Success! r300_float = 0x%x\n\n", *r300_float_out);
80 
81 	if (negate)
82 		return -1;
83 	else
84 		return 1;
85 }
86 
rc_inline_literals(struct radeon_compiler * c,void * user)87 void rc_inline_literals(struct radeon_compiler *c, void *user)
88 {
89 	struct rc_instruction * inst;
90 
91 	for(inst = c->Program.Instructions.Next;
92 					inst != &c->Program.Instructions;
93 					inst = inst->Next) {
94 		const struct rc_opcode_info * info =
95 					rc_get_opcode_info(inst->U.I.Opcode);
96 
97 		unsigned src_idx;
98 		struct rc_constant * constant;
99 		float float_value;
100 		unsigned char r300_float = 0;
101 		int ret;
102 
103 		/* XXX: Handle presub */
104 
105 		/* We aren't using rc_for_all_reads_src here, because presub
106 		 * sources need to be handled differently. */
107 		for (src_idx = 0; src_idx < info->NumSrcRegs; src_idx++) {
108 			unsigned use_literal = 0;
109 			unsigned swz, chan;
110 			struct rc_src_register src_reg = inst->U.I.SrcReg[src_idx];
111 			if (src_reg.File != RC_FILE_CONSTANT) {
112 				continue;
113 			}
114 			constant =
115 				&c->Program.Constants.Constants[src_reg.Index];
116 			if (constant->Type != RC_CONSTANT_IMMEDIATE) {
117 				continue;
118 			}
119 			for (chan = 0; chan < 4; chan++) {
120 				unsigned char r300_float_tmp;
121 				swz = GET_SWZ(src_reg.Swizzle, chan);
122 				if (swz >= RC_SWIZZLE_ZERO) {
123 					continue;
124 				}
125 				float_value = constant->u.Immediate[swz];
126 				ret = ieee_754_to_r300_float(float_value,
127 								&r300_float_tmp);
128 				if (!ret || (use_literal &&
129 						r300_float != r300_float_tmp)) {
130 					use_literal = 0;
131 					break;
132 				}
133 
134 				if (ret == -1 && src_reg.Abs) {
135 					use_literal = 0;
136 					break;
137 				}
138 
139 				if (!use_literal) {
140 					r300_float = r300_float_tmp;
141 					use_literal = 1;
142 				}
143 
144 				/* Use RC_SWIZZLE_W for the inline constant, so
145 				 * it will become one of the alpha sources. */
146 				SET_SWZ(src_reg.Swizzle, chan, RC_SWIZZLE_W);
147 				if (ret == -1) {
148 					src_reg.Negate ^= (1 << chan);
149 				}
150 			}
151 
152 			src_reg.File = RC_FILE_INLINE;
153 			src_reg.Index = r300_float;
154 			if (!use_literal || !c->SwizzleCaps->IsNative(inst->U.I.Opcode, src_reg)) {
155 				continue;
156 			}
157 			inst->U.I.SrcReg[src_idx] = src_reg;
158 		}
159 	}
160 }
161