free(temporaries, temporary);\r
}\r
\r
+ sw::Shader::Opcode OutputASM::getOpcode(sw::Shader::Opcode op, TIntermTyped *in) const\r
+ {\r
+ TBasicType baseType = in->getType().getBasicType();\r
+\r
+ switch(op)\r
+ {\r
+ case sw::Shader::OPCODE_NEG:\r
+ switch(baseType)\r
+ {\r
+ case EbtInt:\r
+ case EbtUInt:\r
+ return sw::Shader::OPCODE_INEG;\r
+ case EbtFloat:\r
+ default:\r
+ return op;\r
+ }\r
+ case sw::Shader::OPCODE_ADD:\r
+ switch(baseType)\r
+ {\r
+ case EbtInt:\r
+ case EbtUInt:\r
+ return sw::Shader::OPCODE_IADD;\r
+ case EbtFloat:\r
+ default:\r
+ return op;\r
+ }\r
+ case sw::Shader::OPCODE_SUB:\r
+ switch(baseType)\r
+ {\r
+ case EbtInt:\r
+ case EbtUInt:\r
+ return sw::Shader::OPCODE_ISUB;\r
+ case EbtFloat:\r
+ default:\r
+ return op;\r
+ }\r
+ case sw::Shader::OPCODE_MUL:\r
+ switch(baseType)\r
+ {\r
+ case EbtInt:\r
+ case EbtUInt:\r
+ return sw::Shader::OPCODE_IMUL;\r
+ case EbtFloat:\r
+ default:\r
+ return op;\r
+ }\r
+ case sw::Shader::OPCODE_DIV:\r
+ switch(baseType)\r
+ {\r
+ case EbtInt:\r
+ return sw::Shader::OPCODE_IDIV;\r
+ case EbtUInt:\r
+ return sw::Shader::OPCODE_UDIV;\r
+ case EbtFloat:\r
+ default:\r
+ return op;\r
+ }\r
+ case sw::Shader::OPCODE_IMOD:\r
+ return baseType == EbtUInt ? sw::Shader::OPCODE_UMOD : op;\r
+ case sw::Shader::OPCODE_ISHR:\r
+ return baseType == EbtUInt ? sw::Shader::OPCODE_USHR : op;\r
+ case sw::Shader::OPCODE_MIN:\r
+ switch(baseType)\r
+ {\r
+ case EbtInt:\r
+ return sw::Shader::OPCODE_IMIN;\r
+ case EbtUInt:\r
+ return sw::Shader::OPCODE_UMIN;\r
+ case EbtFloat:\r
+ default:\r
+ return op;\r
+ }\r
+ case sw::Shader::OPCODE_MAX:\r
+ switch(baseType)\r
+ {\r
+ case EbtInt:\r
+ return sw::Shader::OPCODE_IMAX;\r
+ case EbtUInt:\r
+ return sw::Shader::OPCODE_UMAX;\r
+ case EbtFloat:\r
+ default:\r
+ return op;\r
+ }\r
+ default:\r
+ return op;\r
+ }\r
+ }\r
+\r
void OutputASM::visitSymbol(TIntermSymbol *symbol)\r
{\r
// Vertex varyings don't have to be actively used to successfully link\r
mov->src[0].swizzle = swizzle;\r
}\r
break;\r
- case EOpAddAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_ADD, result, left, left, right); break;\r
- case EOpAdd: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_ADD, result, left, right); break;\r
- case EOpSubAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_SUB, result, left, left, right); break;\r
- case EOpSub: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_SUB, result, left, right); break;\r
- case EOpMulAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_MUL, result, left, left, right); break;\r
- case EOpMul: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_MUL, result, left, right); break;\r
- case EOpDivAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_DIV, result, left, left, right); break;\r
- case EOpDiv: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_DIV, result, left, right); break;\r
+ case EOpAddAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_ADD, result), result, left, left, right); break;\r
+ case EOpAdd: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_ADD, result), result, left, right); break;\r
+ case EOpSubAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_SUB, result), result, left, left, right); break;\r
+ case EOpSub: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_SUB, result), result, left, right); break;\r
+ case EOpMulAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_MUL, result), result, left, left, right); break;\r
+ case EOpMul: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_MUL, result), result, left, right); break;\r
+ case EOpDivAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_DIV, result), result, left, left, right); break;\r
+ case EOpDiv: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_DIV, result), result, left, right); break;\r
+ case EOpIModAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_IMOD, result), result, left, left, right); break;\r
+ case EOpIMod: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_IMOD, result), result, left, right); break;\r
+ case EOpBitShiftLeftAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_SHL, result, left, left, right); break;\r
+ case EOpBitShiftLeft: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_SHL, result, left, right); break;\r
+ case EOpBitShiftRightAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_ISHR, result), result, left, left, right); break;\r
+ case EOpBitShiftRight: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_ISHR, result), result, left, right); break;\r
+ case EOpBitwiseAndAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_AND, result, left, left, right); break;\r
+ case EOpBitwiseAnd: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_AND, result, left, right); break;\r
+ case EOpBitwiseXorAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_XOR, result, left, left, right); break;\r
+ case EOpBitwiseXor: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_XOR, result, left, right); break;\r
+ case EOpBitwiseOrAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_OR, result, left, left, right); break;\r
+ case EOpBitwiseOr: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_OR, result, left, right); break;\r
case EOpEqual:\r
if(visit == PostVisit)\r
{\r
- emitCmp(sw::Shader::CONTROL_EQ, result, left, right);\r
+ emitBinary(sw::Shader::OPCODE_EQ, result, left, right);\r
\r
for(int index = 1; index < left->totalRegisterCount(); index++)\r
{\r
Temporary equal(this);\r
- emitCmp(sw::Shader::CONTROL_EQ, &equal, left, right, index);\r
+ Instruction *eq = emit(sw::Shader::OPCODE_EQ, &equal, left, right);\r
+ argument(eq->src[0], left, index);\r
+ argument(eq->src[1], right, index);\r
emit(sw::Shader::OPCODE_AND, result, result, &equal);\r
}\r
}\r
case EOpNotEqual:\r
if(visit == PostVisit)\r
{\r
- emitCmp(sw::Shader::CONTROL_NE, result, left, right);\r
+ emitBinary(sw::Shader::OPCODE_NE, result, left, right);\r
\r
for(int index = 1; index < left->totalRegisterCount(); index++)\r
{\r
Temporary notEqual(this);\r
- emitCmp(sw::Shader::CONTROL_NE, ¬Equal, left, right, index);\r
+ Instruction *eq = emit(sw::Shader::OPCODE_NE, ¬Equal, left, right);\r
+ argument(eq->src[0], left, index);\r
+ argument(eq->src[1], right, index);\r
emit(sw::Shader::OPCODE_OR, result, result, ¬Equal);\r
}\r
}\r
case EOpGreaterThan: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GT, result, left, right); break;\r
case EOpLessThanEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_LE, result, left, right); break;\r
case EOpGreaterThanEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GE, result, left, right); break;\r
- case EOpVectorTimesScalarAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_MUL, result, left, left, right); break;\r
- case EOpVectorTimesScalar: if(visit == PostVisit) emit(sw::Shader::OPCODE_MUL, result, left, right); break;\r
+ case EOpVectorTimesScalarAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_MUL, left), result, left, left, right); break;\r
+ case EOpVectorTimesScalar: if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_MUL, left), result, left, right); break;\r
case EOpMatrixTimesScalar:\r
if(visit == PostVisit)\r
{\r
return false;\r
}\r
\r
- Constant one(1.0f, 1.0f, 1.0f, 1.0f);\r
- Constant rad(1.74532925e-2f, 1.74532925e-2f, 1.74532925e-2f, 1.74532925e-2f);\r
- Constant deg(5.72957795e+1f, 5.72957795e+1f, 5.72957795e+1f, 5.72957795e+1f);\r
-\r
TIntermTyped *result = node;\r
TIntermTyped *arg = node->getOperand();\r
+ TBasicType basicType = arg->getType().getBasicType();\r
+\r
+ union\r
+ {\r
+ float f;\r
+ int i;\r
+ } one_value;\r
+\r
+ if(basicType == EbtInt || basicType == EbtUInt)\r
+ {\r
+ one_value.i = 1;\r
+ }\r
+ else\r
+ {\r
+ one_value.f = 1.0f;\r
+ }\r
+\r
+ Constant one(one_value.f, one_value.f, one_value.f, one_value.f);\r
+ Constant rad(1.74532925e-2f, 1.74532925e-2f, 1.74532925e-2f, 1.74532925e-2f);\r
+ Constant deg(5.72957795e+1f, 5.72957795e+1f, 5.72957795e+1f, 5.72957795e+1f);\r
\r
switch(node->getOp())\r
{\r
case EOpNegative:\r
if(visit == PostVisit)\r
{\r
+ sw::Shader::Opcode negOpcode = getOpcode(sw::Shader::OPCODE_NEG, arg);\r
for(int index = 0; index < arg->totalRegisterCount(); index++)\r
{\r
- Instruction *neg = emit(sw::Shader::OPCODE_MOV, result, arg);\r
+ Instruction *neg = emit(negOpcode, result, arg);\r
neg->dst.index += index;\r
argument(neg->src[0], arg, index);\r
- neg->src[0].modifier = sw::Shader::MODIFIER_NEGATE;\r
}\r
}\r
break;\r
{\r
copy(result, arg);\r
\r
+ sw::Shader::Opcode addOpcode = getOpcode(sw::Shader::OPCODE_ADD, arg);\r
for(int index = 0; index < arg->totalRegisterCount(); index++)\r
{\r
- Instruction *add = emit(sw::Shader::OPCODE_ADD, arg, arg, &one);\r
+ Instruction *add = emit(addOpcode, arg, arg, &one);\r
add->dst.index += index;\r
argument(add->src[0], arg, index);\r
}\r
{\r
copy(result, arg);\r
\r
+ sw::Shader::Opcode subOpcode = getOpcode(sw::Shader::OPCODE_SUB, arg);\r
for(int index = 0; index < arg->totalRegisterCount(); index++)\r
{\r
- Instruction *sub = emit(sw::Shader::OPCODE_SUB, arg, arg, &one);\r
+ Instruction *sub = emit(subOpcode, arg, arg, &one);\r
sub->dst.index += index;\r
argument(sub->src[0], arg, index);\r
}\r
case EOpPreIncrement:\r
if(visit == PostVisit)\r
{\r
+ sw::Shader::Opcode addOpcode = getOpcode(sw::Shader::OPCODE_ADD, arg);\r
for(int index = 0; index < arg->totalRegisterCount(); index++)\r
{\r
- Instruction *add = emit(sw::Shader::OPCODE_ADD, result, arg, &one);\r
+ Instruction *add = emit(addOpcode, result, arg, &one);\r
add->dst.index += index;\r
argument(add->src[0], arg, index);\r
}\r
case EOpPreDecrement:\r
if(visit == PostVisit)\r
{\r
+ sw::Shader::Opcode subOpcode = getOpcode(sw::Shader::OPCODE_SUB, arg);\r
for(int index = 0; index < arg->totalRegisterCount(); index++)\r
{\r
- Instruction *sub = emit(sw::Shader::OPCODE_SUB, result, arg, &one);\r
+ Instruction *sub = emit(subOpcode, result, arg, &one);\r
sub->dst.index += index;\r
argument(sub->src[0], arg, index);\r
}\r
case EOpMod: if(visit == PostVisit) emit(sw::Shader::OPCODE_MOD, result, arg[0], arg[1]); break;\r
case EOpPow: if(visit == PostVisit) emit(sw::Shader::OPCODE_POW, result, arg[0], arg[1]); break;\r
case EOpAtan: if(visit == PostVisit) emit(sw::Shader::OPCODE_ATAN2, result, arg[0], arg[1]); break;\r
- case EOpMin: if(visit == PostVisit) emit(sw::Shader::OPCODE_MIN, result, arg[0], arg[1]); break;\r
- case EOpMax: if(visit == PostVisit) emit(sw::Shader::OPCODE_MAX, result, arg[0], arg[1]); break;\r
+ case EOpMin: if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_MIN, result), result, arg[0], arg[1]); break;\r
+ case EOpMax: if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_MAX, result), result, arg[0], arg[1]); break;\r
case EOpClamp:\r
if(visit == PostVisit)\r
{\r
- emit(sw::Shader::OPCODE_MAX, result, arg[0], arg[1]);\r
- emit(sw::Shader::OPCODE_MIN, result, result, arg[2]);\r
+ emit(getOpcode(sw::Shader::OPCODE_MAX, result), result, arg[0], arg[1]);\r
+ emit(getOpcode(sw::Shader::OPCODE_MIN, result), result, result, arg[2]);\r
}\r
break;\r
case EOpMix: if(visit == PostVisit) emit(sw::Shader::OPCODE_LRP, result, arg[2], arg[1], arg[0]); break;\r
\r
Instruction *OutputASM::emitCast(TIntermTyped *dst, TIntermTyped *src)\r
{\r
- // Integers are implemented as float\r
- if((dst->getBasicType() == EbtFloat || dst->getBasicType() == EbtInt) && src->getBasicType() == EbtBool)\r
+ switch(src->getBasicType())\r
{\r
- return emit(sw::Shader::OPCODE_B2F, dst, src);\r
- }\r
- if(dst->getBasicType() == EbtBool && (src->getBasicType() == EbtFloat || src->getBasicType() == EbtInt))\r
- {\r
- return emit(sw::Shader::OPCODE_F2B, dst, src);\r
- }\r
- if(dst->getBasicType() == EbtInt && src->getBasicType() == EbtFloat)\r
- {\r
- return emit(sw::Shader::OPCODE_TRUNC, dst, src);\r
+ case EbtBool:\r
+ switch(dst->getBasicType())\r
+ {\r
+ case EbtInt: return emit(sw::Shader::OPCODE_B2I, dst, src);\r
+ case EbtUInt: return emit(sw::Shader::OPCODE_B2U, dst, src);\r
+ case EbtFloat: return emit(sw::Shader::OPCODE_B2F, dst, src);\r
+ default: break;\r
+ }\r
+ break;\r
+ case EbtInt:\r
+ switch(dst->getBasicType())\r
+ {\r
+ case EbtBool: return emit(sw::Shader::OPCODE_I2B, dst, src);\r
+ case EbtFloat: return emit(sw::Shader::OPCODE_I2F, dst, src);\r
+ default: break;\r
+ }\r
+ break;\r
+ case EbtUInt:\r
+ switch(dst->getBasicType())\r
+ {\r
+ case EbtBool: return emit(sw::Shader::OPCODE_U2B, dst, src);\r
+ case EbtFloat: return emit(sw::Shader::OPCODE_U2F, dst, src);\r
+ default: break;\r
+ }\r
+ break;\r
+ case EbtFloat:\r
+ switch(dst->getBasicType())\r
+ {\r
+ case EbtBool: return emit(sw::Shader::OPCODE_F2B, dst, src);\r
+ case EbtInt: return emit(sw::Shader::OPCODE_F2I, dst, src);\r
+ case EbtUInt: return emit(sw::Shader::OPCODE_F2U, dst, src);\r
+ default: break;\r
+ }\r
+ break;\r
+ default:\r
+ break;\r
}\r
\r
return emit(sw::Shader::OPCODE_MOV, dst, src);\r
\r
void OutputASM::emitCmp(sw::Shader::Control cmpOp, TIntermTyped *dst, TIntermNode *left, TIntermNode *right, int index)\r
{\r
- bool boolean = (left->getAsTyped()->getBasicType() == EbtBool);\r
- sw::Shader::Opcode opcode = boolean ? sw::Shader::OPCODE_ICMP : sw::Shader::OPCODE_CMP;\r
+ sw::Shader::Opcode opcode;\r
+ switch(left->getAsTyped()->getBasicType())\r
+ {\r
+ case EbtBool:\r
+ case EbtInt:\r
+ opcode = sw::Shader::OPCODE_ICMP;\r
+ break;\r
+ case EbtUInt:\r
+ opcode = sw::Shader::OPCODE_UCMP;\r
+ break;\r
+ default:\r
+ opcode = sw::Shader::OPCODE_CMP;\r
+ break;\r
+ }\r
\r
Instruction *cmp = emit(opcode, dst, left, right);\r
cmp->control = cmpOp;\r
if(scale == 1)\r
{\r
Constant oldScale((int)dst.rel.scale);\r
- Instruction *mad = emit(sw::Shader::OPCODE_MAD, &address, &address, &oldScale, right);\r
+ Instruction *mad = emit(sw::Shader::OPCODE_IMAD, &address, &address, &oldScale, right);\r
mad->src[0].index = dst.rel.index;\r
mad->src[0].type = dst.rel.type;\r
}\r
else\r
{\r
Constant oldScale((int)dst.rel.scale);\r
- Instruction *mul = emit(sw::Shader::OPCODE_MUL, &address, &address, &oldScale);\r
+ Instruction *mul = emit(sw::Shader::OPCODE_IMUL, &address, &address, &oldScale);\r
mul->src[0].index = dst.rel.index;\r
mul->src[0].type = dst.rel.type;\r
\r
Constant newScale(scale);\r
- emit(sw::Shader::OPCODE_MAD, &address, right, &newScale, &address);\r
+ emit(sw::Shader::OPCODE_IMAD, &address, right, &newScale, &address);\r
}\r
\r
dst.rel.type = sw::Shader::PARAMETER_TEMP;\r
{\r
if(scale == 1)\r
{\r
- emit(sw::Shader::OPCODE_ADD, &address, &address, right);\r
+ emit(sw::Shader::OPCODE_IADD, &address, &address, right);\r
}\r
else\r
{\r
Constant newScale(scale);\r
- emit(sw::Shader::OPCODE_MAD, &address, right, &newScale, &address);\r
+ emit(sw::Shader::OPCODE_IMAD, &address, right, &newScale, &address);\r
}\r
}\r
}\r
int OutputASM::attributeRegister(TIntermTyped *attribute)\r
{\r
ASSERT(!attribute->isArray());\r
- ASSERT(attribute->getBasicType() == EbtFloat);\r
\r
int index = lookup(attributes, attribute);\r
\r