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