Add support for operand negation (-reg)

This commit is contained in:
fincs 2014-11-16 20:52:18 +01:00
parent d41106a672
commit e6e92aff48
2 changed files with 23 additions and 14 deletions

View File

@ -28,11 +28,13 @@ enum
}; };
#define SWIZZLE_COMP(n,v) ((v) << (6-(n)*2)) #define SWIZZLE_COMP(n,v) ((v) << (6-(n)*2))
#define OPDESC_MAKE(out, src1, src2) ((out) | ((src1) << 5) | ((src2) << (5+8+1))) #define OPSRC_MAKE(neg, sw) ((neg) | ((sw) << 1))
#define OPDESC_MAKE(out, src1, src2) ((out) | ((src1) << 4) | ((src2) << (4+9)))
#define FMT_OPCODE(n) ((n)<<26) #define FMT_OPCODE(n) ((n)<<26)
#define OUTPUT_MAKE(i, reg, mask) ((i) | ((reg)<<16) | ((u64)(mask)<<32)) #define OUTPUT_MAKE(i, reg, mask) ((i) | ((reg)<<16) | ((u64)(mask)<<32))
#define DEFAULT_SWIZZLE (SWIZZLE_COMP(0,COMP_X) | SWIZZLE_COMP(1,COMP_Y) | SWIZZLE_COMP(2,COMP_Z) | SWIZZLE_COMP(3,COMP_W)) #define DEFAULT_SWIZZLE (SWIZZLE_COMP(0,COMP_X) | SWIZZLE_COMP(1,COMP_Y) | SWIZZLE_COMP(2,COMP_Z) | SWIZZLE_COMP(3,COMP_W))
#define DEFAULT_OPSRC OPSRC_MAKE(0, DEFAULT_SWIZZLE)
extern std::vector<u32> g_outputBuf; extern std::vector<u32> g_outputBuf;

View File

@ -341,11 +341,12 @@ static int parseSwizzling(const char* b)
// Fill in missing bits // Fill in missing bits
for (int j = i; j < 4; j ++) for (int j = i; j < 4; j ++)
out |= SWIZZLE_COMP(j, q); out |= SWIZZLE_COMP(j, q);
return out; return out<<1;
} }
static int maskFromSwizzling(int sw) static int maskFromSwizzling(int sw)
{ {
sw >>= 1; // get rid of negation bit
int out = 0; int out = 0;
for (int i = 0; i < 4; i ++) for (int i = 0; i < 4; i ++)
out |= BIT(3-((sw>>(i*2))&3)); out |= BIT(3-((sw>>(i*2))&3));
@ -358,15 +359,15 @@ static int findOrAddOpdesc(int& out, int opdesc, bool ignoreOp2=false)
{ {
int cur_opdesc = g_opdescTable[i]; int cur_opdesc = g_opdescTable[i];
if (ignoreOp2) if (ignoreOp2)
cur_opdesc &= ~((0xFF << (5+8+1)) | BIT(31)); // clear bits we don't want to compare cur_opdesc &= ~((0x1FF << (4+9)) | BIT(31)); // clear bits we don't want to compare
else if (cur_opdesc & BIT(31)) else if (cur_opdesc & BIT(31))
{ {
// We can recycle this opdesc which didn't have an explicit Op2 // We can recycle this opdesc which didn't have an explicit Op2
cur_opdesc &= ~BIT(31); cur_opdesc &= ~BIT(31);
int cmp = opdesc &~ (0xFF << (5+8+1)); // partial opdesc used for comparison int cmp = opdesc &~ (0x1FF << (4+9)); // partial opdesc used for comparison
if (cmp == cur_opdesc) if (cmp == cur_opdesc)
{ {
g_opdescTable[i] = cur_opdesc | (opdesc & (0xFF << (5+8+1))); g_opdescTable[i] = cur_opdesc | (opdesc & (0x1FF << (4+9)));
out = i; out = i;
return 0; return 0;
} }
@ -395,12 +396,17 @@ static inline bool isregp(int x)
static int parseReg(char* pos, int& outReg, int& outSw) static int parseReg(char* pos, int& outReg, int& outSw)
{ {
outReg = 0; outReg = 0;
outSw = DEFAULT_SWIZZLE; outSw = DEFAULT_OPSRC;
if (*pos == '-')
{
pos++;
outSw |= 1; // negation bit
}
auto dotPos = strchr(pos, '.'); auto dotPos = strchr(pos, '.');
if (dotPos) if (dotPos)
{ {
*dotPos++ = 0; *dotPos++ = 0;
outSw = parseSwizzling(dotPos); outSw = parseSwizzling(dotPos) | (outSw&1);
if (outSw < 0) if (outSw < 0)
return throwError("invalid swizzling mask: %s\n", dotPos); return throwError("invalid swizzling mask: %s\n", dotPos);
} }
@ -425,14 +431,15 @@ static int parseReg(char* pos, int& outReg, int& outSw)
int x = it->second; int x = it->second;
outReg = x & 0xFF; outReg = x & 0xFF;
outReg += regOffset; outReg += regOffset;
x >>= 8; outSw ^= (x>>8)&1;
x >>= 9;
// Combine swizzling // Combine swizzling
int temp = 0; int temp = outSw & 1;
for (int j = 0; j < 4; j ++) for (int j = 0; j < 4; j ++)
{ {
int comp = (outSw >> (6 - j*2)) & 3; int comp = (outSw >> (7 - j*2)) & 3;
comp = (x >> (6 - comp*2)) & 3; comp = (x >> (6 - comp*2)) & 3;
temp |= SWIZZLE_COMP(j, comp); temp |= SWIZZLE_COMP(j, comp)<<1;
} }
outSw = temp; outSw = temp;
return 0; return 0;
@ -638,7 +645,7 @@ DEF_DIRECTIVE(uniform)
uniform.pos = uniformPos; uniform.pos = uniformPos;
uniform.size = uSize; uniform.size = uSize;
uniformPos += uSize; uniformPos += uSize;
g_aliases.insert( std::pair<std::string,int>(argText, uniform.pos | (DEFAULT_SWIZZLE<<8)) ); g_aliases.insert( std::pair<std::string,int>(argText, uniform.pos | (DEFAULT_OPSRC<<8)) );
#ifdef DEBUG #ifdef DEBUG
printf("uniform %s[%d] @ d%02X:d%02X\n", argText, uSize, uniform.pos, uniform.pos+uSize-1); printf("uniform %s[%d] @ d%02X:d%02X\n", argText, uSize, uniform.pos, uniform.pos+uSize-1);
@ -673,7 +680,7 @@ DEF_DIRECTIVE(const)
ct.param[2] = atof(arg2Text); ct.param[2] = atof(arg2Text);
ct.param[3] = atof(arg3Text); ct.param[3] = atof(arg3Text);
g_aliases.insert( std::pair<std::string,int>(constName, ct.regId | (DEFAULT_SWIZZLE<<8)) ); g_aliases.insert( std::pair<std::string,int>(constName, ct.regId | (DEFAULT_OPSRC<<8)) );
#ifdef DEBUG #ifdef DEBUG
printf("constant %s(%f, %f, %f, %f) @ d%02X\n", constName, ct.param[0], ct.param[1], ct.param[2], ct.param[3], ct.regId); printf("constant %s(%f, %f, %f, %f) @ d%02X\n", constName, ct.param[0], ct.param[1], ct.param[2], ct.param[3], ct.regId);
@ -705,7 +712,7 @@ DEF_DIRECTIVE(out)
if (!validateIdentifier(outName)) if (!validateIdentifier(outName))
return throwError("invalid identifier: %s\n", outName); return throwError("invalid identifier: %s\n", outName);
int sw = DEFAULT_SWIZZLE; int sw = DEFAULT_OPSRC;
auto dotPos = strchr(outType, '.'); auto dotPos = strchr(outType, '.');
if (dotPos) if (dotPos)
{ {