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