xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/r300/compiler/radeon_inline_literals.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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