gallium: Add capability for ARB_robust_buffer_access_behavior.
[mesa.git] / src / gallium / drivers / r300 / compiler / radeon_inline_literals.c
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 }