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 */ 22 static 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 61 void 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