1 /*
2 * Copyright 2012 Advanced Micro Devices, Inc.
3 * Author: Tom Stellard <[email protected]>
4 * SPDX-License-Identifier: MIT
5 */
6
7 #include "radeon_compiler.h"
8 #include "radeon_compiler_util.h"
9 #include "radeon_dataflow.h"
10 #include "radeon_program.h"
11 #include "radeon_program_constants.h"
12 #include "radeon_swizzle.h"
13 #include "util/u_bitcast.h"
14 #include <stdio.h>
15
16 #define VERBOSE 0
17
18 #define DBG(...) do { if (VERBOSE) fprintf(stderr, __VA_ARGS__); } while(0)
19
20 /* IEEE-754:
21 * 22:0 mantissa
22 * 30:23 exponent
23 * 31 sign
24 *
25 * R300:
26 * 0:2 mantissa
27 * 3:6 exponent (bias 7)
28 */
ieee_754_to_r300_float(float f,unsigned char * r300_float_out)29 static int ieee_754_to_r300_float(float f, unsigned char *r300_float_out)
30 {
31 unsigned float_bits = u_bitcast_f2u(f);
32 /* XXX: Handle big-endian */
33 unsigned mantissa = float_bits & 0x007fffff;
34 unsigned biased_exponent = (float_bits & 0x7f800000) >> 23;
35 unsigned negate = !!(float_bits & 0x80000000);
36 int exponent = biased_exponent - 127;
37 unsigned mantissa_mask = 0xff8fffff;
38 unsigned r300_exponent, r300_mantissa;
39
40 DBG("Converting %f (0x%x) to 7-bit:\n", f, float_bits);
41 DBG("Raw exponent = %d\n", exponent);
42
43 if (exponent < -7 || exponent > 8) {
44 DBG("Failed exponent out of range\n\n");
45 return 0;
46 }
47
48 if (mantissa & mantissa_mask) {
49 DBG("Failed mantissa has too many bits:\n"
50 "mantissa=0x%x mantissa_mask=0x%x, and=0x%x\n\n",
51 mantissa, mantissa_mask,
52 mantissa & mantissa_mask);
53 return 0;
54 }
55
56 r300_exponent = exponent + 7;
57 r300_mantissa = (mantissa & ~mantissa_mask) >> 20;
58 *r300_float_out = r300_mantissa | (r300_exponent << 3);
59
60 DBG("Success! r300_float = 0x%x\n\n", *r300_float_out);
61
62 if (negate)
63 return -1;
64 else
65 return 1;
66 }
67
rc_inline_literals(struct radeon_compiler * c,void * user)68 void rc_inline_literals(struct radeon_compiler *c, void *user)
69 {
70 struct rc_instruction * inst;
71
72 for(inst = c->Program.Instructions.Next;
73 inst != &c->Program.Instructions;
74 inst = inst->Next) {
75 const struct rc_opcode_info * info =
76 rc_get_opcode_info(inst->U.I.Opcode);
77
78 unsigned src_idx;
79 struct rc_constant * constant;
80 float float_value;
81 unsigned char r300_float = 0;
82 int ret;
83
84 /* XXX: Handle presub */
85
86 /* We aren't using rc_for_all_reads_src here, because presub
87 * sources need to be handled differently. */
88 for (src_idx = 0; src_idx < info->NumSrcRegs; src_idx++) {
89 unsigned use_literal = 0;
90 unsigned swz, chan;
91 struct rc_src_register src_reg = inst->U.I.SrcReg[src_idx];
92 if (src_reg.File != RC_FILE_CONSTANT) {
93 continue;
94 }
95 constant =
96 &c->Program.Constants.Constants[src_reg.Index];
97 if (constant->Type != RC_CONSTANT_IMMEDIATE) {
98 continue;
99 }
100 for (chan = 0; chan < 4; chan++) {
101 unsigned char r300_float_tmp;
102 swz = GET_SWZ(src_reg.Swizzle, chan);
103 if (swz >= RC_SWIZZLE_ZERO) {
104 continue;
105 }
106 float_value = constant->u.Immediate[swz];
107 ret = ieee_754_to_r300_float(float_value,
108 &r300_float_tmp);
109 if (!ret || (use_literal &&
110 r300_float != r300_float_tmp)) {
111 use_literal = 0;
112 break;
113 }
114
115 if (ret == -1 && src_reg.Abs) {
116 use_literal = 0;
117 break;
118 }
119
120 if (!use_literal) {
121 r300_float = r300_float_tmp;
122 use_literal = 1;
123 }
124
125 /* We can use any swizzle, so if this is ADD it might
126 * be smart to us the same swizzle as the other src uses
127 * so that we potentially enable presubtract later.
128 * Use RC_SWIZZLE_W otherwise, so it will become one of
129 * the alpha sources.
130 */
131 if (info->Opcode == RC_OPCODE_ADD &&
132 GET_SWZ(inst->U.I.SrcReg[1 - src_idx].Swizzle, chan) == chan) {
133 SET_SWZ(src_reg.Swizzle, chan, chan);
134 } else {
135 SET_SWZ(src_reg.Swizzle, chan, RC_SWIZZLE_W);
136 }
137 if (ret == -1) {
138 src_reg.Negate ^= (1 << chan);
139 }
140 }
141
142 src_reg.File = RC_FILE_INLINE;
143 src_reg.Index = r300_float;
144 if (!use_literal || !c->SwizzleCaps->IsNative(inst->U.I.Opcode, src_reg)) {
145 continue;
146 }
147 inst->U.I.SrcReg[src_idx] = src_reg;
148 }
149 }
150 }
151