Add auto-NOP insertion to work around flow-of-control PICA errata
This commit is contained in:
parent
d7a3af7c52
commit
05d9e79095
@ -62,6 +62,7 @@ enum
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Output buffer
|
// Output buffer
|
||||||
|
#define MAX_VSH_SIZE 512
|
||||||
typedef std::vector<u32> outputBufType;
|
typedef std::vector<u32> outputBufType;
|
||||||
typedef outputBufType::iterator outputBufIter;
|
typedef outputBufType::iterator outputBufIter;
|
||||||
extern outputBufType g_outputBuf;
|
extern outputBufType g_outputBuf;
|
||||||
@ -142,6 +143,8 @@ extern labelTableType g_labels;
|
|||||||
extern relocTableType g_labelRelocTable;
|
extern relocTableType g_labelRelocTable;
|
||||||
extern aliasTableType g_aliases;
|
extern aliasTableType g_aliases;
|
||||||
|
|
||||||
|
extern bool g_autoNop;
|
||||||
|
|
||||||
int AssembleString(char* str, const char* initialFilename);
|
int AssembleString(char* str, const char* initialFilename);
|
||||||
int RelocateProduct(void);
|
int RelocateProduct(void);
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
static const char* curFile = NULL;
|
static const char* curFile = NULL;
|
||||||
static int curLine = -1;
|
static int curLine = -1;
|
||||||
|
static bool lastWasEnd = false;
|
||||||
|
|
||||||
std::vector<u32> g_outputBuf;
|
std::vector<u32> g_outputBuf;
|
||||||
|
|
||||||
@ -23,6 +24,8 @@ std::vector<Constant> g_constArray;
|
|||||||
int g_constArraySize = -1;
|
int g_constArraySize = -1;
|
||||||
const char* g_constArrayName;
|
const char* g_constArrayName;
|
||||||
|
|
||||||
|
bool g_autoNop = true;
|
||||||
|
|
||||||
class UniformAlloc
|
class UniformAlloc
|
||||||
{
|
{
|
||||||
int start, end, bound, tend;
|
int start, end, bound, tend;
|
||||||
@ -795,6 +798,14 @@ static inline bool isBadInputRegCombination(int a, int b, int c)
|
|||||||
return isBadInputRegCombination(a,b) || isBadInputRegCombination(b,c) || isBadInputRegCombination(c,a);
|
return isBadInputRegCombination(a,b) || isBadInputRegCombination(b,c) || isBadInputRegCombination(c,a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void insertPaddingNop()
|
||||||
|
{
|
||||||
|
if (g_autoNop)
|
||||||
|
BUF.push_back(FMT_OPCODE(MAESTRO_NOP));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "%s:%d: warning: a padding NOP is required here\n", curFile, curLine);
|
||||||
|
}
|
||||||
|
|
||||||
DEF_COMMAND(format0)
|
DEF_COMMAND(format0)
|
||||||
{
|
{
|
||||||
ENSURE_NO_MORE_ARGS();
|
ENSURE_NO_MORE_ARGS();
|
||||||
@ -1245,6 +1256,21 @@ DEF_DIRECTIVE(else)
|
|||||||
if (elem.uExtra)
|
if (elem.uExtra)
|
||||||
return throwError("spurious .else\n");
|
return throwError("spurious .else\n");
|
||||||
|
|
||||||
|
// Automatically add padding NOPs when necessary
|
||||||
|
if (lastWasEnd)
|
||||||
|
{
|
||||||
|
insertPaddingNop();
|
||||||
|
lastWasEnd = false;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
u32 p = BUF.size();
|
||||||
|
u32 lastOpcode = BUF[p-1] >> 26;
|
||||||
|
if (lastOpcode == MAESTRO_JMPC || lastOpcode == MAESTRO_JMPU
|
||||||
|
|| lastOpcode == MAESTRO_CALL || lastOpcode == MAESTRO_CALLC || lastOpcode == MAESTRO_CALLU
|
||||||
|
|| (p - elem.pos) < 2)
|
||||||
|
insertPaddingNop();
|
||||||
|
}
|
||||||
|
|
||||||
u32 curPos = BUF.size();
|
u32 curPos = BUF.size();
|
||||||
elem.uExtra = curPos;
|
elem.uExtra = curPos;
|
||||||
u32& inst = BUF[elem.pos];
|
u32& inst = BUF[elem.pos];
|
||||||
@ -1265,6 +1291,24 @@ DEF_DIRECTIVE(end)
|
|||||||
return throwError(".end with unmatched block\n");
|
return throwError(".end with unmatched block\n");
|
||||||
|
|
||||||
StackEntry& elem = g_stack[--g_stackPos];
|
StackEntry& elem = g_stack[--g_stackPos];
|
||||||
|
|
||||||
|
// Automatically add padding NOPs when necessary
|
||||||
|
if (elem.type != SE_ARRAY && lastWasEnd)
|
||||||
|
{
|
||||||
|
insertPaddingNop();
|
||||||
|
lastWasEnd = false;
|
||||||
|
}
|
||||||
|
else if (elem.type == SE_PROC || elem.type == SE_FOR || elem.type == SE_IF && BUF.size() > 0)
|
||||||
|
{
|
||||||
|
u32 p = BUF.size();
|
||||||
|
u32 lastOpcode = BUF[p-1] >> 26;
|
||||||
|
if (lastOpcode == MAESTRO_JMPC || lastOpcode == MAESTRO_JMPU
|
||||||
|
|| lastOpcode == MAESTRO_CALL || lastOpcode == MAESTRO_CALLC || lastOpcode == MAESTRO_CALLU
|
||||||
|
|| (elem.type == SE_FOR && lastOpcode == MAESTRO_BREAKC)
|
||||||
|
|| (elem.type != SE_ARRAY && (p - elem.pos) < (elem.type != SE_PROC ? 2 : 1)))
|
||||||
|
insertPaddingNop();
|
||||||
|
}
|
||||||
|
|
||||||
u32 curPos = BUF.size();
|
u32 curPos = BUF.size();
|
||||||
u32 size = curPos - elem.pos;
|
u32 size = curPos - elem.pos;
|
||||||
|
|
||||||
@ -1287,6 +1331,7 @@ DEF_DIRECTIVE(end)
|
|||||||
u32& inst = BUF[elem.pos];
|
u32& inst = BUF[elem.pos];
|
||||||
inst &= ~(0xFFF << 10);
|
inst &= ~(0xFFF << 10);
|
||||||
inst |= (curPos-1) << 10;
|
inst |= (curPos-1) << 10;
|
||||||
|
lastWasEnd = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1307,6 +1352,7 @@ DEF_DIRECTIVE(end)
|
|||||||
inst &= ~0x3FF;
|
inst &= ~0x3FF;
|
||||||
inst |= curPos - elem.uExtra;
|
inst |= curPos - elem.uExtra;
|
||||||
}
|
}
|
||||||
|
lastWasEnd = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1814,6 +1860,12 @@ int ProcessCommand(const char* cmd)
|
|||||||
table = dirTable;
|
table = dirTable;
|
||||||
} else if (!g_stackPos)
|
} else if (!g_stackPos)
|
||||||
return throwError("instruction outside block\n");
|
return throwError("instruction outside block\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastWasEnd = false;
|
||||||
|
if (!GetDvleData()->isGeoShader && g_outputBuf.size() >= MAX_VSH_SIZE)
|
||||||
|
return throwError("instruction outside vertex shader code memory (max %d instructions, currently %d)\n", MAX_VSH_SIZE, g_outputBuf.size());
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; table[i].name; i ++)
|
for (int i = 0; table[i].name; i ++)
|
||||||
if (stricmp(table[i].name, cmd) == 0)
|
if (stricmp(table[i].name, cmd) == 0)
|
||||||
|
@ -36,6 +36,7 @@ int usage(const char* prog)
|
|||||||
"Options:\n"
|
"Options:\n"
|
||||||
" -o, --out=<file> Specifies the name of the SHBIN file to generate\n"
|
" -o, --out=<file> Specifies the name of the SHBIN file to generate\n"
|
||||||
" -h, --header=<file> Specifies the name of the header file to generate\n"
|
" -h, --header=<file> Specifies the name of the header file to generate\n"
|
||||||
|
" -n, --no-nop Disables the automatic insertion of padding NOPs\n"
|
||||||
" -v, --version Displays version information\n"
|
" -v, --version Displays version information\n"
|
||||||
, prog);
|
, prog);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@ -50,18 +51,20 @@ int main(int argc, char* argv[])
|
|||||||
{ "out", required_argument, NULL, 'o' },
|
{ "out", required_argument, NULL, 'o' },
|
||||||
{ "header", required_argument, NULL, 'h' },
|
{ "header", required_argument, NULL, 'h' },
|
||||||
{ "help", no_argument, NULL, '?' },
|
{ "help", no_argument, NULL, '?' },
|
||||||
|
{ "no-nop", no_argument, NULL, 'n' },
|
||||||
{ "version",no_argument, NULL, 'v' },
|
{ "version",no_argument, NULL, 'v' },
|
||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
int opt, optidx = 0;
|
int opt, optidx = 0;
|
||||||
while ((opt = getopt_long(argc, argv, "o:h:?v", long_options, &optidx)) != -1)
|
while ((opt = getopt_long(argc, argv, "o:h:?nv", long_options, &optidx)) != -1)
|
||||||
{
|
{
|
||||||
switch (opt)
|
switch (opt)
|
||||||
{
|
{
|
||||||
case 'o': shbinFile = optarg; break;
|
case 'o': shbinFile = optarg; break;
|
||||||
case 'h': hFile = optarg; break;
|
case 'h': hFile = optarg; break;
|
||||||
case '?': usage(argv[0]); return EXIT_SUCCESS;
|
case '?': usage(argv[0]); return EXIT_SUCCESS;
|
||||||
|
case 'n': g_autoNop = false; break;
|
||||||
case 'v': printf("%s - Built on %s %s\n", PACKAGE_STRING, __DATE__, __TIME__); return EXIT_SUCCESS;
|
case 'v': printf("%s - Built on %s %s\n", PACKAGE_STRING, __DATE__, __TIME__); return EXIT_SUCCESS;
|
||||||
default: return usage(argv[0]);
|
default: return usage(argv[0]);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user