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
|
||||
#define MAX_VSH_SIZE 512
|
||||
typedef std::vector<u32> outputBufType;
|
||||
typedef outputBufType::iterator outputBufIter;
|
||||
extern outputBufType g_outputBuf;
|
||||
@ -142,6 +143,8 @@ extern labelTableType g_labels;
|
||||
extern relocTableType g_labelRelocTable;
|
||||
extern aliasTableType g_aliases;
|
||||
|
||||
extern bool g_autoNop;
|
||||
|
||||
int AssembleString(char* str, const char* initialFilename);
|
||||
int RelocateProduct(void);
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
static const char* curFile = NULL;
|
||||
static int curLine = -1;
|
||||
static bool lastWasEnd = false;
|
||||
|
||||
std::vector<u32> g_outputBuf;
|
||||
|
||||
@ -23,6 +24,8 @@ std::vector<Constant> g_constArray;
|
||||
int g_constArraySize = -1;
|
||||
const char* g_constArrayName;
|
||||
|
||||
bool g_autoNop = true;
|
||||
|
||||
class UniformAlloc
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
ENSURE_NO_MORE_ARGS();
|
||||
@ -1245,6 +1256,21 @@ DEF_DIRECTIVE(else)
|
||||
if (elem.uExtra)
|
||||
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();
|
||||
elem.uExtra = curPos;
|
||||
u32& inst = BUF[elem.pos];
|
||||
@ -1265,6 +1291,24 @@ DEF_DIRECTIVE(end)
|
||||
return throwError(".end with unmatched block\n");
|
||||
|
||||
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 size = curPos - elem.pos;
|
||||
|
||||
@ -1287,6 +1331,7 @@ DEF_DIRECTIVE(end)
|
||||
u32& inst = BUF[elem.pos];
|
||||
inst &= ~(0xFFF << 10);
|
||||
inst |= (curPos-1) << 10;
|
||||
lastWasEnd = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1307,6 +1352,7 @@ DEF_DIRECTIVE(end)
|
||||
inst &= ~0x3FF;
|
||||
inst |= curPos - elem.uExtra;
|
||||
}
|
||||
lastWasEnd = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1814,6 +1860,12 @@ int ProcessCommand(const char* cmd)
|
||||
table = dirTable;
|
||||
} else if (!g_stackPos)
|
||||
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 ++)
|
||||
if (stricmp(table[i].name, cmd) == 0)
|
||||
|
@ -36,6 +36,7 @@ int usage(const char* prog)
|
||||
"Options:\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"
|
||||
" -n, --no-nop Disables the automatic insertion of padding NOPs\n"
|
||||
" -v, --version Displays version information\n"
|
||||
, prog);
|
||||
return EXIT_FAILURE;
|
||||
@ -50,18 +51,20 @@ int main(int argc, char* argv[])
|
||||
{ "out", required_argument, NULL, 'o' },
|
||||
{ "header", required_argument, NULL, 'h' },
|
||||
{ "help", no_argument, NULL, '?' },
|
||||
{ "no-nop", no_argument, NULL, 'n' },
|
||||
{ "version",no_argument, NULL, 'v' },
|
||||
{ NULL, 0, NULL, 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)
|
||||
{
|
||||
case 'o': shbinFile = 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;
|
||||
default: return usage(argv[0]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user