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