diff options
| author | Andrew M. B. Boktor <[email protected]> | 2012-04-18 16:32:54 -0800 |
|---|---|---|
| committer | Andrew Boktor <[email protected]> | 2014-08-14 13:19:05 -0700 |
| commit | 5a65fb7a5f0cb1a8d7831bae33749e8bd15a947d (patch) | |
| tree | 9fb3040a0d43c426471aab94c92c41f2ea113780 /cuobjdump_to_ptxplus | |
| parent | 49aaf1cd2cab61dea239264643f25e71251d1ce1 (diff) | |
Merging
//depot/gpgpu_sim_research/fermi-test/cuobjdump_to_ptxplus/...
to //depot/gpgpu_sim_research/fermi/distribution/cuobjdump_to_ptxplus/...
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 12022]
Diffstat (limited to 'cuobjdump_to_ptxplus')
| -rw-r--r-- | cuobjdump_to_ptxplus/Makefile | 145 | ||||
| -rw-r--r-- | cuobjdump_to_ptxplus/cuobjdump.l | 96 | ||||
| -rw-r--r-- | cuobjdump_to_ptxplus/cuobjdump.y | 83 | ||||
| -rw-r--r-- | cuobjdump_to_ptxplus/cuobjdumpInst.cc | 1690 | ||||
| -rw-r--r-- | cuobjdump_to_ptxplus/cuobjdumpInst.h | 22 | ||||
| -rw-r--r-- | cuobjdump_to_ptxplus/cuobjdumpInstList.cc | 553 | ||||
| -rw-r--r-- | cuobjdump_to_ptxplus/cuobjdumpInstList.h | 47 | ||||
| -rw-r--r-- | cuobjdump_to_ptxplus/cuobjdump_to_ptxplus.cc | 162 | ||||
| -rw-r--r-- | cuobjdump_to_ptxplus/elf.l | 114 | ||||
| -rw-r--r-- | cuobjdump_to_ptxplus/elf.y | 81 | ||||
| -rw-r--r-- | cuobjdump_to_ptxplus/ptx_parser.h | 336 | ||||
| -rw-r--r-- | cuobjdump_to_ptxplus/sass.l | 324 | ||||
| -rw-r--r-- | cuobjdump_to_ptxplus/sass.y | 405 |
13 files changed, 4058 insertions, 0 deletions
diff --git a/cuobjdump_to_ptxplus/Makefile b/cuobjdump_to_ptxplus/Makefile new file mode 100644 index 0000000..f58a0fd --- /dev/null +++ b/cuobjdump_to_ptxplus/Makefile @@ -0,0 +1,145 @@ +BOOST_ROOT ?= /usr/include/boost + +LEX = flex +LEXFLAGS = -B +YACC = bison +YFLAGS = -t -d -v --report=all +CC = gcc +CCFLAGS = -ggdb -I${BOOST_ROOT} -lboost_regex -lboost_filesystem -fPIC +CXX = g++ +CXXFLAGS = ${CCFLAGS} +LD = g++ +LDFLAGS = ${CCFLAGS} + + +CUOBJDUMP_PARSER_OBJECTS = cuobjdump_parser.o cuobjdump_lexer.o +SASS_PARSER_OBJECTS = sass_lexer.o sass_parser.o +ELF_PARSER_OBJECTS = elf_lexer.o elf_parser.o +HEADER_PARSER_OBJECTS = headerParser.o headerLexer.o +PTX_PARSER_OBJECTS = ptx.tab.o lex.ptx_.o + +all: cuobjdump_to_ptxplus + +cuobjdump_to_ptxplus: stringList.o decudaInst.o decudaInstList.o cuobjdumpInst.o cuobjdumpInstList.o cuobjdump_to_ptxplus.o $(PTX_PARSER_OBJECTS) $(SASS_PARSER_OBJECTS) $(ELF_PARSER_OBJECTS) $(HEADER_PARSER_OBJECTS) $(CUOBJDUMP_PARSER_OBJECTS) + ${LD} ${LDFLAGS} -ocuobjdump_to_ptxplus stringList.o decudaInst.o decudaInstList.o headerParser.o headerLexer.o cuobjdumpInst.o cuobjdumpInstList.o cuobjdump_to_ptxplus.o lex.ptx_.o ptx.tab.o $(SASS_PARSER_OBJECTS) $(ELF_PARSER_OBJECTS) + +stringList.o: ../decuda_to_ptxplus/stringList.cc ../decuda_to_ptxplus/stringList.h + ${CXX} ${CXXFLAGS} -c -ostringList.o ../decuda_to_ptxplus/stringList.cc + +decudaInst.o: ../decuda_to_ptxplus/decudaInst.cc ../decuda_to_ptxplus/decudaInst.h ../decuda_to_ptxplus/stringList.h + ${CXX} ${CXXFLAGS} -c -odecudaInst.o ../decuda_to_ptxplus/decudaInst.cc + +decudaInstList.o: ../decuda_to_ptxplus/decudaInstList.cc ../decuda_to_ptxplus/decudaInstList.h ../decuda_to_ptxplus/decudaInst.h + ${CXX} ${CXXFLAGS} -c -odecudaInstList.o ../decuda_to_ptxplus/decudaInstList.cc + +cuobjdumpInst.o: cuobjdumpInst.cc cuobjdumpInst.h ../decuda_to_ptxplus/decudaInst.h ./decudaInstList.h + ${CXX} ${CXXFLAGS} -c -ocuobjdumpInst.o cuobjdumpInst.cc + +cuobjdumpInstList.o: cuobjdumpInstList.cc cuobjdumpInstList.h ../decuda_to_ptxplus/decudaInstList.h + ${CXX} ${CXXFLAGS} -c -ocuobjdumpInstList.o cuobjdumpInstList.cc + +#sassParser.cpp: sassParser.y ../distribution/decuda_to_ptxplus/decudaInstList.h cuobjdumpInstList.h +# ${YACC} ${YFLAGS} -osassParser.cpp sassParser.y + +#sassParser.hpp: sassParser.cpp + +#sassLexer.cpp: sassLexer.l sassParser.hpp +# ${LEX} ${LEXFLAGS} -osassLexer.cpp sassLexer.l + +headerParser.cpp : ../decuda_to_ptxplus/header.y ../decuda_to_ptxplus/decudaInstList.h + ${YACC} ${YFLAGS} --name-prefix=header_ -oheaderParser.cpp ../decuda_to_ptxplus/header.y + +headerParser.hpp : headerParser.cpp + +headerLexer.cpp : ../decuda_to_ptxplus/header.l headerParser.hpp + ${LEX} ${LEXFLAGS} -oheaderLexer.cpp ../decuda_to_ptxplus/header.l + +#sassLexer.o: sassLexer.cpp +# ${CXX} ${CXXFLAGS} -c -Igenerated -osassLexer.o sassLexer.cpp +# +#sassParser.o: sassParser.cpp ../distribution/decuda_to_ptxplus/stringList.h ../distribution/decuda_to_ptxplus/decudaInst.h ../distribution/decuda_to_ptxplus/decudaInstList.h cuobjdumpInstList.h +# ${CXX} ${CXXFLAGS} -c -Igenerated -osassParser.o sassParser.cpp + +headerLexer.o : headerLexer.cpp + ${CXX} ${CXXFLAGS} -c -Igenerated -oheaderLexer.o headerLexer.cpp + +headerParser.o : headerParser.cpp ../decuda_to_ptxplus/stringList.h ../decuda_to_ptxplus/decudaInst.h ./decudaInstList.h + ${CXX} ${CXXFLAGS} -c -Igenerated -oheaderParser.o headerParser.cpp + +decudaInstList.h : ../decuda_to_ptxplus/decudaInstList.h ./decudaInst.h + rm -f decudaInstList.h + ln -s ../decuda_to_ptxplus/decudaInstList.h decudaInstList.h + +decudaInst.h : ../decuda_to_ptxplus/decudaInst.h ./stringList.h + rm -f decudaInst.h + ln -s ../decuda_to_ptxplus/decudaInst.h decudaInst.h + +stringList.h : ../decuda_to_ptxplus/stringList.h + rm -f stringList.h + ln -s ../decuda_to_ptxplus/stringList.h stringList.h + +cuobjdump_to_ptxplus.o: cuobjdump_to_ptxplus.cc ../decuda_to_ptxplus/decudaInstList.h cuobjdumpInstList.h + ${CXX} ${CXXFLAGS} -c -ocuobjdump_to_ptxplus.o cuobjdump_to_ptxplus.cc + +lex.ptx_.c : ../src/cuda-sim/ptx.l + ${LEX} ${LEXFLAGS} ../src/cuda-sim/ptx.l + +ptx.tab.c : ../src/cuda-sim/ptx.y + ${YACC} ${YFLAGS} --name-prefix=ptx_ -v ../src/cuda-sim/ptx.y + +ptx.tab.h : ptx.tab.c + +lex.ptx_.o : lex.ptx_.c ptx.tab.h + rm -f opcodes.def opcodes.h + ln -s ../src/cuda-sim/opcodes.def opcodes.def + ln -s ../src/cuda-sim/opcodes.h opcodes.h + ${CXX} ${CXXFLAGS} -c lex.ptx_.c + +ptx.tab.o : ptx.tab.c ptx_parser.h + ${CXX} ${CXXFLAGS} -c ptx.tab.c + +.PRECIOUS: %.c %.h %_lexer.c %_parser.c %_parser.h %_parser.cpp %_parser.hpp %_lexer.cpp + +%_lexer.c: %.l %_parser.h + $(LEX) $(LEXFLAGS) -P $*_ -o$@ $< + +%_lexer.cpp: %.l %_parser.hpp + $(LEX) $(LEXFLAGS) -P $*_ -o$@ $< + +%_parser.c: %.y + $(YACC) $(YFLAGS) -p $*_ -o$@ $< + +%_parser.cpp: %.y + $(YACC) $(YFLAGS) -p $*_ -o$@ $< + +# The ':' is needed otherwise make gets confused and doesn't understand that it knows how to make %Parser.hpp from %Parser.cpp. +# : in bash is equivalent to NOP (no operation) +%_parser.h: %_parser.c + : + +%_parser.hpp: %_parser.cpp + : + +cuobjdump_parser.o: cuobjdump_parser.c + ${CC} ${CCFLAGS} -c -o $@ $< + +cuobjdump_lexer.o: cuobjdump_lexer.c + ${CC} ${CCFLAGS} -c -o $@ $< + +%.o: %.cpp + $(CXX) ${CXXFLAGS} -c -o $@ $< + +clean: + rm -f ./opcodes.def ./opcodes.h + rm -f ./lex.ptx_.c ./ptx.tab.c ./ptx.tab.h ./lex.ptx_.o ./ptx.tab.o ptx.output + rm -f ./decudaInstList.h ./decudaInst.h ./stringList.h + rm -f ./headerParser.o ./headerLexer.o ./headerParser.cpp ./headerParser.hpp ./headerLexer.cpp ./headerParser.output + rm -f ./stringList.o ./decudaInst.o ./decudaInstList.o + rm -f ./cuobjdumpInstList.o ./cuobjdumpInst.o + rm -f ./sass_lexer.o ./sass_parser.o ./cuobjdump_to_ptxplus.o + rm -f ./sass_parser.hpp ./sass_parser.output + rm -f ./sass_parser.cpp ./sass_lexer.cpp + rm -f ./cuobjdump_to_ptxplus + rm -f ./cuobjdump_parser.o ./cuobjdump_parser.c ./cuobjdump_parser.output ./cuobjdump_parser.h + rm -f ./cuobjdump_lexer.o ./cuobjdump_lexer.c + rm -f ./elf_lexer.o ./elf_parser.o ./elf_lexer.cpp ./elf_parser.cpp ./elf_parser.hpp ./elf_parser.output diff --git a/cuobjdump_to_ptxplus/cuobjdump.l b/cuobjdump_to_ptxplus/cuobjdump.l new file mode 100644 index 0000000..fcd43f8 --- /dev/null +++ b/cuobjdump_to_ptxplus/cuobjdump.l @@ -0,0 +1,96 @@ + /*Lex file for output of cuobjdump*/ +%{ +#include <stdio.h> +#include <string.h> +#include "cuobjdump_parser.h" + +#define YY_NEVER_INTERACTIVE 1 + +#define YYDEBUG 1 + +#define yylval cuobjdump_lval + +void cuobjdump_error(const char*); +%} + +%option stack +%option noyywrap +%option yylineno + +%s ptxcode +%s sasscode +%s elfcode +%s header +%s endheader + +alpha [a-zA-Z] +numeric [0-9] +whitespace [ \t] +newline [\n] +notnewline [^\n] +newlines {newline}+ +%% + + +"ptxasOptions"{notnewline}*{newline} +[1-9]{numeric}* yylval.string_value = strdup(yytext); return DECIMAL; + + +"Fatbin ptx code:"{newline} { + yy_push_state(ptxcode); + yy_push_state(header); + yylval.string_value = strdup(yytext); + return PTXHEADER; +} +"Fatbin elf code:"{newline} { + yy_push_state(elfcode); + yy_push_state(header); + yylval.string_value = strdup(yytext); + return ELFHEADER; +} + /*PTX code tokens*/ +<ptxcode>{notnewline}*{newline} yylval.string_value = strdup(yytext); return PTXLINE; + + /*ELF code tokens*/ +<elfcode>{whitespace}*"code for sm_"{numeric}+{newline} { + BEGIN(sasscode); + yylval.string_value = strdup(yytext); + return SASSLINE; +} +<elfcode>{notnewline}*{newline} yylval.string_value = strdup(yytext); return ELFLINE; + + /*SASS code tokens*/ +<sasscode>{notnewline}*{newline} yylval.string_value = strdup(yytext); return SASSLINE; + + /*Header tokens*/ +<header>[[:alnum:]_]+ yylval.string_value = strdup(yytext); return IDENTIFIER; +<header>"================" return H_SEPARATOR; +<header>"arch = " return H_ARCH; +<header>"code version = " return H_CODEVERSION; +<header>\[{numeric},{numeric}\] return CODEVERSION; +<header>"producer = " return H_PRODUCER; +<header>"host = " return H_HOST; +<header>"compile_size = " return H_COMPILESIZE; +<header>"identifier = " BEGIN(endheader); return H_IDENTIFIER; +<header>"has debug info"{newline} + + /* Looking for the identifier (filename) then the header is done */ +<endheader>[[:alnum:]_\.]+{newline} yylval.string_value = strdup(yytext); yy_pop_state(); return FILENAME; + + +{newline} return NEWLINE; + + /*Reached end of file*/ +<<EOF>> return 0; + + /*No other rule matched. Throw an error*/ +. cuobjdump_error("Invalid token"); + +%% +void cuobjdump_error(const char* message) +{ + printf(" "); printf(message); printf(" near \""); printf(yytext); printf("\""); + printf(" on line "); + char line[5]; sprintf(line, "%i", yylineno); printf(line); + printf("\n"); +} diff --git a/cuobjdump_to_ptxplus/cuobjdump.y b/cuobjdump_to_ptxplus/cuobjdump.y new file mode 100644 index 0000000..0b20a83 --- /dev/null +++ b/cuobjdump_to_ptxplus/cuobjdump.y @@ -0,0 +1,83 @@ + /*Yacc file for output of cuobjdump*/ +%{ +#include <stdio.h> + +int yylex(void); +void yyerror(const char*); +extern void addCuobjdumpSection(int sectiontype); +void setCuobjdumparch(const char* arch); +void setCuobjdumpidentifier(const char* identifier); +void setCuobjdumpptxfilename(const char* filename); +void setCuobjdumpelffilename(const char* filename); +void setCuobjdumpsassfilename(const char* filename); +int elfserial = 1; +int ptxserial = 1; +FILE *ptxfile; +FILE *elffile; +FILE *sassfile; +char filename [1024]; +%} +%union { + char* string_value; +} +%token <string_value> H_SEPARATOR H_ARCH H_CODEVERSION H_PRODUCER H_HOST H_COMPILESIZE H_IDENTIFIER +%token <string_value> CODEVERSION +%token <string_value> STRING +%token <string_value> FILENAME +%token <string_value> DECIMAL +%token <string_value> PTXHEADER ELFHEADER +%token <string_value> PTXLINE +%token <string_value> ELFLINE +%token <string_value> SASSLINE +%token <string_value> IDENTIFIER +%token <string_value> NEWLINE + +%% + +program : emptylines section + | program section; + +emptylines : emptylines NEWLINE + | ; + +section : PTXHEADER { + addCuobjdumpSection(0); + snprintf(filename, 1024, "_cuobjdump_%d.ptx", ptxserial++); + ptxfile = fopen(filename, "w"); + setCuobjdumpptxfilename(filename); + } headerinfo ptxcode { + fclose(ptxfile); + } + | ELFHEADER { + addCuobjdumpSection(1); + snprintf(filename, 1024, "_cuobjdump_%d.elf", elfserial); + elffile = fopen(filename, "w"); + setCuobjdumpelffilename(filename); + } headerinfo elfcode { + fclose(elffile); + snprintf(filename, 1024, "_cuobjdump_%d.sass", elfserial++); + sassfile = fopen(filename, "w"); + setCuobjdumpsassfilename(filename); + } sasscode { + fclose(sassfile); + }; + +headerinfo : H_SEPARATOR NEWLINE + H_ARCH IDENTIFIER NEWLINE + H_CODEVERSION CODEVERSION NEWLINE + H_PRODUCER IDENTIFIER NEWLINE + H_HOST IDENTIFIER NEWLINE + H_COMPILESIZE IDENTIFIER NEWLINE + H_IDENTIFIER FILENAME {setCuobjdumparch($4); setCuobjdumpidentifier($19);}; + +ptxcode : ptxcode PTXLINE {fprintf(ptxfile, "%s", $2);} + | ; + +elfcode : elfcode ELFLINE {fprintf(elffile, "%s", $2);} + | ; + +sasscode : sasscode SASSLINE {fprintf(sassfile, "%s", $2)} + | ; + + +%% diff --git a/cuobjdump_to_ptxplus/cuobjdumpInst.cc b/cuobjdump_to_ptxplus/cuobjdumpInst.cc new file mode 100644 index 0000000..b014888 --- /dev/null +++ b/cuobjdump_to_ptxplus/cuobjdumpInst.cc @@ -0,0 +1,1690 @@ +#include "cuobjdumpInst.h" +#include <sstream> +#include <iostream> + +extern void output(const char * text); + +//Constructor +cuobjdumpInst::cuobjdumpInst() +{ + //initilize everything to empty +} + +bool cuobjdumpInst::checkCubojdumpLabel(std::list<std::string> labelList, std::string label) +{ + if(labelList.empty()) + return false; + + std::list<std::string>::iterator labelIterator; + + for( labelIterator=labelList.begin(); labelIterator!=labelList.end(); labelIterator++ ) + { + if(label.compare(*labelIterator) == 0) + return true; + } + + return false; +} + +void cuobjdumpInst::printCuobjdumpLabel(std::list<std::string> labelList) +{ + if((strcmp(m_label, "")!=0)&&(checkCubojdumpLabel(labelList, m_label))) { + output(m_label); + output(": "); + } +} + +void cuobjdumpInst::printCuobjdumpPredicate() +{ + stringListPiece* currentPiece = m_predicate->getListStart(); + if(currentPiece!=NULL) + { + output("@$p"); + char modString[2]; + modString[0]=currentPiece->stringText[1]; + modString[1]='\0'; + output(modString); + + stringListPiece* currentPiece2 = m_predicateModifiers->getListStart(); + for(int i=0; (i<m_predicateModifiers->getSize())&&(currentPiece2!=NULL); i++) + { + const char* modString2 = currentPiece2->stringText; + char* modString3 = new char[strlen(currentPiece2->stringText)+1]; + + for(int i=0; i<strlen(modString2); i++) + { + if(modString2[i] >= 'A' && modString2[i] <= 'Z') + modString3[i] = modString2[i] + 32; + else + modString3[i] = modString2[i]; + } + modString3[strlen(modString2)]='\0'; + if( strcmp(modString3, ".not_sign")==0) + { + output(".nsf"); + } else if( strcmp(modString3, ".sign")==0) + { + output(".sf"); + } else if( strcmp(modString3, ".carry")==0) + { + output(".cf"); + } + else + { + output(modString3); + } + currentPiece = currentPiece2->nextString; + } + output(" "); + } +} + +void cuobjdumpInst::printCuobjdumpTypeModifiers() +{ + stringListPiece* currentPiece = m_typeModifiers->getListStart(); + for(int i=0; (i<m_typeModifiers->getSize())&&(currentPiece!=NULL); i++) + { + const char* modString = currentPiece->stringText; + if( strcmp(modString, ".F16")==0 ) + output(".f16"); + else if( strcmp(modString, ".F32")==0 ) + output(".f32"); + else if( strcmp(modString, ".F64")==0 ) + output(".ff64"); + else if( strcmp(modString, ".S8")==0 ) + output(".s8"); + else if( strcmp(modString, ".S16")==0 ) + output(".s16"); + else if( strcmp(modString, ".S32")==0 ) + output(".s32"); + else if( strcmp(modString, ".S64")==0 ) + output(".bb64"); //TODO: might have to change to .ss64 in the future. + else if( strcmp(modString, ".S128")==0 ) + output(".bb128"); //TODO: might have to change to .ss64 in the future. + else if( strcmp(modString, ".U8")==0 ) + output(".u8"); + else if( strcmp(modString, ".U16")==0 ) + output(".u16"); + else if( strcmp(modString, ".U32")==0 ) + output(".u32"); + else if( strcmp(modString, ".U64")==0 ) + output(".bb64"); //TODO: might have to change to .ss64 in the future. + else if( strcmp(modString, ".HI")==0 ) + output(".hi"); + else + { + printf("Unknown Type: "); + printf(modString); + printf("\n"); + output("Unknown Type: "); output(modString); + assert(0); + } + + currentPiece = currentPiece->nextString; + } +} + +void cuobjdumpInst::printCuobjdumpBaseModifiers() +{ + stringListPiece* currentPiece = m_baseModifiers->getListStart(); + for(int i=0; (i<m_baseModifiers->getSize())&&(currentPiece!=NULL); i++) + { + const char* modString = currentPiece->stringText; + if( strcmp(modString, "EQ")==0 ) + output(".eq"); + else if( strcmp(modString, "EQU")==0 ) + output(".equ"); + else if( strcmp(modString, "GE")==0 ) + output(".ge"); + else if( strcmp(modString, "GEU")==0 ) + output(".geu"); + else if( strcmp(modString, "GT")==0 ) + output(".gt"); + else if( strcmp(modString, "GTU")==0 ) + output(".gtu"); + else if( strcmp(modString, "LE")==0 ) + output(".le"); + else if( strcmp(modString, "LEU")==0 ) + output(".leu"); + else if( strcmp(modString, "LT")==0 ) + output(".lt"); + else if( strcmp(modString, "LTU")==0 ) + output(".ltu"); + else if( strcmp(modString, "NE")==0 ) + output(".ne"); + else if( strcmp(modString, "NEU")==0 ) + output(".neu"); + else if( strcmp(modString, ".exit")==0 ) + output(modString); + else if( strcmp(modString, ".abs")==0 ) + { + if((strcmp(m_base, "F2F")!=0) && (strcmp(m_base, "I2I")!=0)) + { + output(modString); + } + } + else if( strcmp(modString, "ex2")==0 ) + output(modString); + else if( strcmp(modString, "sin")==0 ) + output(modString); + else if( strcmp(modString, "cos")==0 ) + output(modString); + else if( strcmp(modString, ".rz")==0 ) + output(modString); + else if( strcmp(modString, ".bext")==0 ) + { + //".bext" is a modifier that indicated u8 to u16 type conversion, I think + } + else if( strcmp(modString, ".s")==0 ) + { + //".s" is the same as ".join" in decuda. + } + else if( strcmp(modString, ".sfu")==0 ) + { + //".sfu" is an unknown base modifier, TODO: find out what it is + } + else if( strcmp(modString, ".x")==0 ) + { + //".x" is an unknown base modifier, TODO: find out what it is + output(modString); + } + else if( strcmp(modString, ".e")==0 ) + { + //".e" is an unknown base modifier, TODO: find out what it is + output(modString); + } + else if( strcmp(modString, ".ir")==0 ) + { + //".ir" is an unknown base modifier, TODO: find out what it is + output(modString); + } + else if(strcmp(modString, "IADD")==0 || + strcmp(modString, "IMIN")==0 || + strcmp(modString, "IMAX")==0 + //strcmp(modString, "INC")==0 || + //strcmp(modString, "DEC")==0 || + //strcmp(modString, "IAND")==0 || + //strcmp(modString, "IOR")==0 || + //strcmp(modString, "IXOR")==0 + ) + { + /* + * This is the case of a GRED or GATOM operation + */ + output("."); + std::string modstr = modString; + modstr = modstr.substr(1); + for (int i=0; i<modstr.length(); i++){ + modstr[i] = tolower(modstr[i]); + } + output(modstr.c_str()); + } + else + { + printf("Unknown Base Mod: "); + printf(modString); + printf("\n"); + output("Unknown Base Mod: "); + output(modString); + assert(0); + } + + currentPiece = currentPiece->nextString; + } +} + +/* + * Remove the trailing 'l' or 'h' and output the operand followed by ".lo" or ".hi" respectively + */ +void cuobjdumpInst::printCuobjdumpOperandlohi(std::string op) { + if (op.substr(op.length()-1) == "l") { + output(op.substr(0, op.length()-1).c_str()); + output(".lo"); + } else if (op.substr(op.length()-1) == "h"){ + output(op.substr(0, op.length()-1).c_str()); + output(".hi"); + } else { + output(op.c_str()); + } +} + +void cuobjdumpInst::printCuobjdumpOperand(stringListPiece* currentPiece, std::string operandDelimiter, const char* base) +{ + + output(operandDelimiter.c_str()); + output(" "); + + //Current piece + std::string currp = currentPiece->stringText; + std::string mod; + + if(currp[0] == '-') { + mod = currp.substr(1); + + if(mod.substr(0,2) == "0x") { + unsigned int immValue; + std::stringstream hexStringConvert2; + hexStringConvert2 << std::hex << mod; + hexStringConvert2 >> immValue; + + if(immValue){ + immValue = ~immValue + 1; + } + + std::stringstream outputhexstream; + outputhexstream << std::hex << immValue; + std::string outputhex; + outputhex = outputhexstream.str(); + output("0x"); + for(int i=8; i > outputhex.length(); i--) + { + output("0"); + } + output(outputhex.c_str()); + return; + } + + output("-"); + } + else + { + mod = std::string(currp); + } + + // Make it lower case + if(mod.substr(0,9)!= "constant1") + for(int i=0; i<mod.length(); i++) + { + mod[i] = tolower(mod[i]); + } + + //double destination + if(mod[0]=='.') //double destination + { + std::string temp = mod.substr(2,2); + output("$p"); + output(mod.substr(2,2).c_str()); + + mod = mod.substr(4); + } + + + if(mod == "g [0x1].u16") { //handling special register case: %ntid.x + output("%%ntid.x"); + } else if(mod == "g [0x2].u16") { //handling special register case: %ntid.y + output("%%ntid.y"); + } else if(mod == "g [0x3].u16") { //handling special register case: %ntid.x + output("%%ntid.z"); + } else if(mod =="g [0x4].u16") { //handling special register case: %nctaid.x + output("%%nctaid.x"); + } else if(mod =="g [0x5].u16") { //handling special register case: %nctaid.y + output("%%nctaid.y"); + } else if(mod == "g [0x6].u16") {//handling special register case: %ctaid.x + output("%%ctaid.x"); + } else if(mod == "g [0x7].u16") {//handling special register case: %ctaid.y + output("%%ctaid.y"); + } else if(mod[0]=='r') { //basic register + if( (strcmp(m_base, "DADD")==0) || + (strcmp(m_base, "DMUL")==0) || + (strcmp(m_base, "DFMA")==0) || + ( (m_typeModifiers->getSize()==1) && + (strcmp((m_typeModifiers->getListStart()->stringText), ".S64")==0) && + ( (strcmp(m_base, "G2R")==0) || + (strcmp(m_base, "R2G")==0) || + (strcmp(m_base, "GLD")==0) || + (strcmp(m_base, "GST")==0) || + (strcmp(m_base, "LST")==0) ))) { + std::string modsub = mod.substr(1); + int regNumInt = atoi(modsub.c_str()); + std::stringstream temp; + temp << "{$r" << (regNumInt) << ",$r"<< (regNumInt+1) << "}"; + output(temp.str().c_str()); + } else if( (m_typeModifiers->getSize()==1) && + (strcmp((m_typeModifiers->getListStart()->stringText), ".S128")==0)) { + std::string modsub = mod.substr(1); + int regNumInt = atoi(modsub.c_str()); + std::stringstream temp; + temp << "{$r" << (regNumInt); + temp << ",$r" << (regNumInt+1); + temp << ",$r" << (regNumInt+2); + temp << ",$r" << (regNumInt+3) << "}"; + output(temp.str().c_str()); + } else { + output("$"); + printCuobjdumpOperandlohi(mod); + } + } else if(mod[0] == 'c' && mod.length() == 2) { //predicate register (conditional code) + output("$p"); + output(mod.substr(1,1).c_str()); + } else if(mod[0]=='a') {//offset register + output("$ofs"); + mod = mod.substr(1); + printCuobjdumpOperandlohi(mod); + } else if(mod[0]=='o') {//output register + output("$o127"); + } else if ( mod[0]=='g' || + mod.substr(0,2) == "lo" || + mod.substr(0,8) == "constant") { + //memory operands, global14 = global, g = shared, c = constant + std::string modsub; + std::string modsub2; + std::string modsub3; + modsub = mod.c_str(); + int localFlag = 0; + + if(mod.find("global14") != std::string::npos) { + //Those instructions don't need the dereferencing done by g [*] + if( strcmp(base,"GRED")==0 || + strcmp(base, "GATOM")==0 || + strcmp(base, "GST")==0 || + strcmp(base, "GLD")==0) + output("["); + else + output("g["); + } else if(mod[0]=='g') { + //Shared memory + output("s["); + } else if(mod.find("local") != std::string::npos) { + modsub3 = modsub.substr(4, modsub.length()-10); + output(modsub3.c_str()); + output("["); + localFlag = 1; + } else if(mod.substr(0,9) == "constant1") { + output(modsub.substr(0, modsub.find_first_of("[]")+1).c_str()); + } else if(mod.substr(0,9)=="constant0"){ + output("constant0["); + } else { + printf("Unidentified modifier: %s\n", mod.c_str()); + assert(0); + } + + modsub = modsub.substr(modsub.find_first_of("[]")+1); + modsub = modsub.substr(0, modsub.length()-1); + //Here we handle whatever was inside the [] + int plusequalFlag = 0; + if(modsub.find("+++") != std::string::npos) { + plusequalFlag = 1; + } + + if(modsub.find("+") != std::string::npos) + { + //Handle a1+++0x1 or a1+0x1 + modsub2 = modsub.substr(modsub.find("+")+1); + + output("$ofs"); + output(modsub.substr(1,1).c_str()); + + if(plusequalFlag == 1) { + output("+="); + } else { + output("+"); + } + + + if(modsub2[0]=='r') { + output("$"); + printCuobjdumpOperandlohi(modsub2); + } else { + modsub2 = modsub2.substr(2); + unsigned int addrValue; + std::stringstream hexStringConvert; + hexStringConvert << std::hex << modsub2; + hexStringConvert >> addrValue; + unsigned chunksize = 4; + if ( this->m_typeModifiers->getSize()>0 && + ( strcmp((m_typeModifiers->getListStart()->stringText), ".S16")==0 || + strcmp((m_typeModifiers->getListStart()->stringText), ".U16")==0 )) chunksize = 2; + if ( this->m_typeModifiers->getSize()>0 && + ( strcmp((m_typeModifiers->getListEnd()->stringText), ".U8")==0 || + strcmp((m_typeModifiers->getListEnd()->stringText), ".S8")==0 )) chunksize = 1; + addrValue = addrValue*chunksize; + char outputHex[10]; + sprintf(outputHex, "%x", addrValue); + std::stringstream outputhex; + outputhex << std::hex << addrValue; + output("0x"); + for(int i=4; i > outputhex.str().length(); i--) + { + output("0"); + } + output(outputhex.str().c_str()); + } + } else { + if(modsub[0]=='r') { + //Register + output("$"); + printCuobjdumpOperandlohi(modsub); + } else { + // Immediate offset + mod = mod.substr(2); + + unsigned int addrValue; + std::stringstream hexStringConvert; + hexStringConvert << std::hex << modsub; + hexStringConvert >> addrValue; + + if(localFlag == 0) + { + unsigned chunksize = 4; + if ( this->m_typeModifiers->getSize()>0 && + (strcmp((m_typeModifiers->getListStart()->stringText), ".S16")==0 || + strcmp((m_typeModifiers->getListStart()->stringText), ".U16")==0 )) chunksize = 2; + addrValue = addrValue*chunksize; + } + std::stringstream outputhex; + outputhex << std::hex << addrValue; + output("0x"); + for(int i=4; i > outputhex.str().length(); i--) { + output("0"); + } + output(outputhex.str().c_str()); + } + } + output("]"); + } else if(mod.substr(0,2) == "0x") { //immediate value + output("0x"); + std::string outputhex; + outputhex = mod.substr(2); + + for(int i=8; i > outputhex.length(); i--) { + output("0"); + } + output(outputhex.c_str()); + } else if(mod.substr(0,3) == "l0x") { //label + output(mod.c_str()); + } else {//variable name + output(mod.c_str()); + } +} + +void cuobjdumpInst::printCuobjdumpOperands() +{ + stringListPiece* currentPiece = m_operands->getListStart(); + std::string delimiter = ""; + for(int i=0; (i<m_operands->getSize())&&(currentPiece!=NULL); i++) + { + if((strcmp(m_base, "LOP.PASS_B")==0 || strcmp(m_base, "LOP.S.PASS_B")==0) && (i==1)) + { + currentPiece = currentPiece->nextString; + continue; + } + printCuobjdumpOperand(currentPiece, delimiter, m_base); + currentPiece = currentPiece->nextString; + delimiter = ","; + } +} + +char * int_default_mod () { return ".u32" ;} + + +std::string breaktarget; + +void cuobjdumpInst::printCuobjdumpPtxPlus(std::list<std::string> labelList, std::list<std::string> texList) +{ + stringListPiece* currentPiece; + + printCuobjdumpLabel(labelList); + + if(strcmp(m_base, "")==0) + { + } + else if(strcmp(m_base, ".entry")==0) + { + /*do nothing here*/ + } + else if(strcmp(m_base, "BAR.ARV.WAIT b0, 0xfff")==0) + { + printCuobjdumpPredicate(); + output("bar.sync 0x00000000;"); + } + else if(strcmp(m_base, "ADA")==0) + { + printCuobjdumpPredicate(); + output("add"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(int_default_mod()); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "BRA")==0) + { + printCuobjdumpPredicate(); + output("bra"); + printCuobjdumpBaseModifiers(); + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "CAL")==0) + { + printCuobjdumpPredicate(); + output("callp"); + printCuobjdumpBaseModifiers(); + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "COS")==0) + { + printCuobjdumpPredicate(); + //output("nop;"); + //output(" //cos"); + output("cos"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + } + else if(strcmp(m_base, "DADD")==0) + { + printCuobjdumpPredicate(); + output("add"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".ff64"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "DFMA")==0) + { + printCuobjdumpPredicate(); + output("mad"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".ff64"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "DMUL")==0) + { + printCuobjdumpPredicate(); + output("mul"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".ff64"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "EX2")==0) + { + printCuobjdumpPredicate(); + //output("nop;"); + //output(" //ex2"); + output("ex2"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "F2F")==0) + { + printCuobjdumpPredicate(); + + int absFlag = 0; + stringListPiece* currentPiece = m_baseModifiers->getListStart(); + + while(currentPiece != NULL) + { + if(strcmp(currentPiece->stringText, ".abs")==0) + { + output("abs"); + absFlag = 1; + break; + } + currentPiece = currentPiece->nextString; + } + if(absFlag == 0) + { + output("cvt"); + } + + printCuobjdumpBaseModifiers(); + + if(absFlag == 0) + { + printCuobjdumpTypeModifiers(); + } + else + { + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + } + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "F2I")==0) + { + printCuobjdumpPredicate(); + output("cvt"); + printCuobjdumpBaseModifiers(); + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "FADD")==0 || strcmp(m_base, "FADD32I")==0) + { + printCuobjdumpPredicate(); + output("add"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "FADD32")==0) + { + printCuobjdumpPredicate(); + output("add.half"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "FMAD")==0 || strcmp(m_base, "FMAD32I")==0) + { + printCuobjdumpPredicate(); + output("mad"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "FMUL")==0 || strcmp(m_base, "FMUL32I")==0) + { + printCuobjdumpPredicate(); + output("mul"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "FMUL32")==0) + { + printCuobjdumpPredicate(); + output("mul.half"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "FSET")==0) + { + printCuobjdumpPredicate(); + output("set"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + { + output(".f32"); output(".f32"); + } + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "G2R")==0) + { + printCuobjdumpPredicate(); + output("mov"); + printCuobjdumpBaseModifiers(); + + if( m_typeModifiers->getSize() == 2 ) { + std::string type1, type2, type; + int type1Size, type2Size; + stringListPiece* currentPiece = m_typeModifiers->getListStart(); + type1 = currentPiece->stringText; + type2 = currentPiece->nextString->stringText; + + type1Size = atoi(type1.substr(2, type1.size()-2).c_str()); + type2Size = atoi(type2.substr(2, type2.size()-2).c_str()); + type = (type1Size < type2Size) ? type1 : type2; + + if( strcmp(type.c_str(), ".F16")==0 ) + output(".f16"); + else if( strcmp(type.c_str(), ".F32")==0 ) + output(".f32"); + else if( strcmp(type.c_str(), ".F64")==0 ) + output(".ff64"); + else if( strcmp(type.c_str(), ".S8")==0 ) + output(".s8"); + else if( strcmp(type.c_str(), ".S16")==0 ) + output(".s16"); + else if( strcmp(type.c_str(), ".S32")==0 ) + output(".s32"); + else if( strcmp(type.c_str(), ".S64")==0 ) + output(".bb64"); + else if( strcmp(type.c_str(), ".S128")==0 ) + output(".bb128"); + else if( strcmp(type.c_str(), ".U8")==0 ) + output(".u8"); + else if( strcmp(type.c_str(), ".U16")==0 ) + output(".u16"); + else if( strcmp(type.c_str(), ".U32")==0 ) + output(".u32"); + else if( strcmp(type.c_str(), ".U64")==0 ) + output(".bb64"); + else + output(type.c_str()); + } else if( m_typeModifiers->getSize() == 1 ) { + printCuobjdumpTypeModifiers(); + } else { + output("Error: unsupported number of type modifiers. "); + } + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "GLD")==0) + { + printCuobjdumpPredicate(); + //output("mov"); + output("ld.global"); + printCuobjdumpBaseModifiers(); + if (strcmp(m_typeModifiers->getListStart()->stringText, ".S128")==0) { + output(".v4.u32"); + } else if (strcmp(m_typeModifiers->getListStart()->stringText, ".S64")==0) { + output(".v2.u32"); + } else { + printCuobjdumpTypeModifiers(); + } + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "GST")==0) + { + printCuobjdumpPredicate(); + //output("mov"); + output("st.global"); + printCuobjdumpBaseModifiers(); + if (strcmp(m_typeModifiers->getListStart()->stringText, ".S128")==0) { + output(".v4.u32"); + } else if (strcmp(m_typeModifiers->getListStart()->stringText, ".S64")==0) { + output(".v2.u32"); + } else { + printCuobjdumpTypeModifiers(); + } + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "I2F")==0) + { + printCuobjdumpPredicate(); + output("cvt"); + printCuobjdumpBaseModifiers(); + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "I2I")==0) + { + printCuobjdumpPredicate(); + + int absFlag = 0; + int bextFlag = 0; + stringListPiece* currentPiece = m_baseModifiers->getListStart(); + + while(currentPiece != NULL) + { + if(strcmp(currentPiece->stringText, ".abs")==0) + { + output("abs"); + absFlag = 1; + break; + } + if(strcmp(currentPiece->stringText, ".bext")==0) + { + bextFlag = 1; + break; + } + currentPiece = currentPiece->nextString; + } + if(absFlag == 0) + { + output("cvt"); + } + + printCuobjdumpBaseModifiers(); + + currentPiece = this->m_typeModifiers->getListStart(); + unsigned int maxlength=16; + unsigned int currlength = 16; + bool issigned = false; + std::string tmpstr; + while(currentPiece != NULL) + { + tmpstr = currentPiece->stringText; + if(tmpstr[1] == 'S') + { + issigned = true; + } + if(tmpstr.substr(2,2) == "32") {currlength=32;} + if (currlength > maxlength) {maxlength = currlength;} + currentPiece = currentPiece->nextString; + } + + if(absFlag == 0) + { + if(bextFlag == 0) + printCuobjdumpTypeModifiers(); + else{ + output("."); + if (issigned) {output("s");} + else {output("u");} + std::stringstream tmp; + tmp << maxlength; + output(tmp.str().c_str()); + output("."); + if (issigned) {output("s");} + else {output("u");} + output("8"); + //output(".u16.u8"); + } + } + else + { + output(int_default_mod()); //TODO: setting default type modifier but I'm not sure if this is right. + } + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "IADD")==0) + { + printCuobjdumpPredicate(); + output("add"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(int_default_mod()); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "IADD32")==0 || strcmp(m_base, "IADD32I")==0 ) + { + printCuobjdumpPredicate(); + output("add.half"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".u32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "IMAD")==0 || strcmp(m_base, "IMAD32I")==0 || strcmp(m_base, "IMAD32")==0) + { + printCuobjdumpPredicate(); + output("mad.lo"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(int_default_mod()); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "IMAD.U24")==0) + { + printCuobjdumpPredicate(); + output("mad24.lo"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".u32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "IMAD.S24")==0) + { + printCuobjdumpPredicate(); + output("mad24.lo"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".s32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "IMUL32I.U24.U24")==0 || + strcmp(m_base, "IMUL32I.S24.S24")==0 || + strcmp(m_base, "IMUL32.U24.U24")==0 || + strcmp(m_base, "IMUL32.S24.S24")==0 || + strcmp(m_base, "IMUL.U24.U24")==0 || + strcmp(m_base, "IMUL.S24.S24")==0) + { + printCuobjdumpPredicate(); + output("mul24.lo"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + { + output(".u32"); //TODO: setting default type modifier but I'm not sure if this is right. + } + else if(m_typeModifiers->getSize() == 2) + { + std::string type1, type2, type; + int type1Size, type2Size; + stringListPiece* currentPiece = m_typeModifiers->getListStart(); + char tempString[5]; + + type1 = currentPiece->stringText; + type2 = currentPiece->nextString->stringText; + + type1Size = atoi(type1.substr(2, type1.size()-2).c_str()); + type2Size = atoi(type2.substr(2, type2.size()-2).c_str()); + type = (type1Size > type2Size) ? type1 : type2; + strcpy(tempString, type.c_str()); + /*if(type1Size==16 && type2Size==16) + output(".lo");*/ + if(tempString[1] >= 'A' && tempString[1] <= 'Z') + tempString[1] += 32; + output(tempString); + } + else + { + printCuobjdumpTypeModifiers(); + } + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "IMUL")==0 || strcmp(m_base, "IMUL32I")==0) + { + printCuobjdumpPredicate(); + output("mul.lo"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + { + output(int_default_mod()); //TODO: setting default type modifier but I'm not sure if this is right. + } + else if(m_typeModifiers->getSize() == 2) + { + std::string type1, type2, type; + int type1Size, type2Size; + stringListPiece* currentPiece = m_typeModifiers->getListStart(); + char tempString[5]; + + type1 = currentPiece->stringText; + type2 = currentPiece->nextString->stringText; + + type1Size = atoi(type1.substr(2, type1.size()-2).c_str()); + type2Size = atoi(type2.substr(2, type2.size()-2).c_str()); + type = (type1Size > type2Size) ? type1 : type2; + strcpy(tempString, type.c_str()); + /*if(type1Size==16 && type2Size==16) + output(".lo");*/ + if(tempString[1] >= 'A' && tempString[1] <= 'Z') + tempString[1] += 32; + output(tempString); + } + else + { + printCuobjdumpTypeModifiers(); + } + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "IMUL32")==0) + { + printCuobjdumpPredicate(); + output("mul.half.lo"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 2) + { + std::string type1, type2, type; + int type1Size, type2Size; + stringListPiece* currentPiece = m_typeModifiers->getListStart(); + char tempString[5]; + + type1 = currentPiece->stringText; + type2 = currentPiece->nextString->stringText; + + type1Size = atoi(type1.substr(2, type1.size()-2).c_str()); + type2Size = atoi(type2.substr(2, type2.size()-2).c_str()); + type = (type1Size > type2Size) ? type1 : type2; + strcpy(tempString, type.c_str()); + /*if(type1Size==16 && type2Size==16) + output(".lo");*/ + if(tempString[1] >= 'A' && tempString[1] <= 'Z') + tempString[1] += 32; + output(tempString); + + } + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "IMUL32.S24.S24")==0) + { + printCuobjdumpPredicate(); + output("mul24.half.lo"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + { + output(".u32"); //TODO: setting default type modifier but I'm not sure if this is right. + } + else if(m_typeModifiers->getSize() == 2) + { + std::string type1, type2, type; + int type1Size, type2Size; + stringListPiece* currentPiece = m_typeModifiers->getListStart(); + char tempString[5]; + + type1 = currentPiece->stringText; + type2 = currentPiece->nextString->stringText; + + type1Size = atoi(type1.substr(2, type1.size()-2).c_str()); + type2Size = atoi(type2.substr(2, type2.size()-2).c_str()); + type = (type1Size > type2Size) ? type1 : type2; + strcpy(tempString, type.c_str()); + /*if(type1Size==16 && type2Size==16) + output(".lo");*/ + if(tempString[1] >= 'A' && tempString[1] <= 'Z') + tempString[1] += 32; + output(tempString); + + } + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "ISET")==0) + { + printCuobjdumpPredicate(); + output("set"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".u32.u32"); //TODO: setting default type modifier but I'm not sure if this is right. + else if(m_typeModifiers->getSize() == 1) + { + printCuobjdumpTypeModifiers(); printCuobjdumpTypeModifiers(); + } + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "LG2")==0) + { + printCuobjdumpPredicate(); + output("lg2"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "LST")==0) + { + printCuobjdumpPredicate(); + output("mov"); + printCuobjdumpBaseModifiers(); + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "MVC")==0) { + printCuobjdumpPredicate(); + output("cvt"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".u32.u32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + + else if(strcmp(m_base, "MOV")==0 || strcmp(m_base, "MVI")==0 || strcmp(m_base, "MVC")==0) + { + printCuobjdumpPredicate(); + output("mov"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(int_default_mod()); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "MOV32")==0) + { + printCuobjdumpPredicate(); + output("mov.half"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".u32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "NOP")==0 || strcmp(m_base, "SSY")==0) + { + printCuobjdumpPredicate(); + output("nop"); + printCuobjdumpBaseModifiers(); + output(";"); + } + else if(strcmp(m_base, "LLD")==0) + { + printCuobjdumpPredicate(); + output("mov"); + printCuobjdumpBaseModifiers(); + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "LOP.AND")==0 || strcmp(m_base, "LOP.S.AND")==0) + { + printCuobjdumpPredicate(); + output("and"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".b32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "LOP.OR")==0 || strcmp(m_base, "LOP.S.OR")==0) + { + printCuobjdumpPredicate(); + output("or"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".b32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "LOP.PASS_B")==0 || strcmp(m_base, "LOP.S.PASS_B")==0) + { + printCuobjdumpPredicate(); + output("not"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".b32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "LOP.XOR")==0 || strcmp(m_base, "LOP.S.XOR")==0) + { + printCuobjdumpPredicate(); + output("xor"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".b32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "R2A")==0) + { + printCuobjdumpPredicate(); + output("shl"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".b32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + if(m_operands->getSize() == 2) + output(", 0x0"); + output(";"); + } + else if(strcmp(m_base, "R2G.U16.U8")==0){ + /* + * This code handles a cuobjdump bug that causes the wrong register number to be printed + */ + printCuobjdumpPredicate(); + output("mov.u8"); + stringListPiece* currentPiece = m_operands->getListStart(); + std::string delimiter = ""; + printCuobjdumpOperand(currentPiece, delimiter, m_base); + output(", "); + std::string curr = currentPiece->nextString->stringText; + curr = curr.substr(1); + int regnum; + std::istringstream(curr)>>regnum; + output("$r"); + std::stringstream finalregnum; + finalregnum << (regnum/2); + output(finalregnum.str().c_str()); + output( regnum%2==0? ".lo": ".hi"); + output(";"); + } + else if(strcmp(m_base, "R2G")==0) + { + printCuobjdumpPredicate(); + output("mov"); + printCuobjdumpBaseModifiers(); + + if( m_typeModifiers->getSize() == 2 ) { + std::string type1, type2, type; + int type1Size, type2Size; + stringListPiece* currentPiece = m_typeModifiers->getListStart(); + type1 = currentPiece->stringText; + type2 = currentPiece->nextString->stringText; + + type1Size = atoi(type1.substr(2, type1.size()-2).c_str()); + type2Size = atoi(type2.substr(2, type2.size()-2).c_str()); + type = (type1Size < type2Size) ? type1 : type2; + + if( strcmp(type.c_str(), ".F16")==0 ) + output(".f16"); + else if( strcmp(type.c_str(), ".F32")==0 ) + output(".f32"); + else if( strcmp(type.c_str(), ".F64")==0 ) + output(".ff64"); + else if( strcmp(type.c_str(), ".S8")==0 ) + output(".s8"); + else if( strcmp(type.c_str(), ".S16")==0 ) + output(".s16"); + else if( strcmp(type.c_str(), ".S32")==0 ) + output(".s32"); + else if( strcmp(type.c_str(), ".S64")==0 ) + output(".bb64"); + else if( strcmp(type.c_str(), ".S128")==0 ) + output(".bb128"); + else if( strcmp(type.c_str(), ".U8")==0 ) + output(".u8"); + else if( strcmp(type.c_str(), ".U16")==0 ) + output(".u16"); + else if( strcmp(type.c_str(), ".U32")==0 ) + output(".u32"); + else if( strcmp(type.c_str(), ".U64")==0 ) + output(".bb64"); + else + output(type.c_str()); + } else if( m_typeModifiers->getSize() == 1 ) { + printCuobjdumpTypeModifiers(); + } else { + output("Error: unsupported number of type modifiers. "); + } + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "RCP")==0) + { + printCuobjdumpPredicate(); + output("rcp"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "RCP32")==0) + { + printCuobjdumpPredicate(); + output("rcp.half"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".f32"); + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "RET")==0) + { + printCuobjdumpPredicate(); + output("retp;"); + } + else if(strcmp(m_base, "RRO")==0) + { + output("nop; //"); + printCuobjdumpPredicate(); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "RSQ")==0) + { + printCuobjdumpPredicate(); + output("rsqrt"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "SHL")==0) + { + printCuobjdumpPredicate(); + output("shl"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(int_default_mod()); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "SHR")==0) + { + printCuobjdumpPredicate(); + output("shr"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(int_default_mod()); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "SIN")==0) + { + printCuobjdumpPredicate(); + output("sin"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + } + else if(strcmp(m_base, "S2R")==0) + { + printCuobjdumpPredicate(); + output("cvt"); + printCuobjdumpBaseModifiers(); + + if(m_typeModifiers->getSize() == 0) + output(".u32"); + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + } + else if(strcmp(m_base, "LD")==0) + { + printCuobjdumpPredicate(); + output("mov"); + printCuobjdumpBaseModifiers(); + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "STS")==0) + { + printCuobjdumpPredicate(); + output("mov"); + printCuobjdumpBaseModifiers(); + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "BAR")==0) + { + printCuobjdumpPredicate(); + output("bar.sync 0;"); + } + else if(strcmp(m_base, "LDS")==0) + { + // If there is not global address space that includes shared memory, then fix this. + // Same for STS + printCuobjdumpPredicate(); + output("mov"); + printCuobjdumpBaseModifiers(); + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "ST")==0) + { + printCuobjdumpPredicate(); + output("mov"); + printCuobjdumpBaseModifiers(); + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } else if(strcmp(m_base, "IMIN")==0) { + printCuobjdumpPredicate(); + output("min"); + printCuobjdumpBaseModifiers(); + if(m_typeModifiers->getSize() == 0) + output(".s32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } else if(strcmp(m_base, "IMAX")==0) { + printCuobjdumpPredicate(); + output("max"); + printCuobjdumpBaseModifiers(); + if(m_typeModifiers->getSize() == 0) + output(".s32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } else if(strcmp(m_base, "FMIN")==0) { + printCuobjdumpPredicate(); + output("min"); + printCuobjdumpBaseModifiers(); + if(m_typeModifiers->getSize() == 0) + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "FMAX")==0) { + printCuobjdumpPredicate(); + output("max"); + printCuobjdumpBaseModifiers(); + if(m_typeModifiers->getSize() == 0) + output(".f32"); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if(strcmp(m_base, "A2R")==0) { + printCuobjdumpPredicate(); + output("mov"); + printCuobjdumpBaseModifiers(); + if(m_typeModifiers->getSize() == 0) + output(int_default_mod()); //TODO: setting default type modifier but I'm not sure if this is right. + else + printCuobjdumpTypeModifiers(); + printCuobjdumpOperands(); + output(";"); + } + else if((strcmp(m_base, "TEX")==0) || + (strcmp(m_base, "TEX32")==0)) { + printCuobjdumpPredicate(); + output("tex.1d.v4.f32.s32 "); + stringListPiece *currPiece; + stringListPiece reg; + std::string addrReg, tex_id; + currPiece = m_operands->getListStart(); + output("{"); + printCuobjdumpOperand(currPiece, "", ""); + output(",_,_,_} , "); + reg = *currPiece; + currPiece = currPiece->nextString; + tex_id = currPiece->stringText; + unsigned int tex_id_int; + std::stringstream ss; + ss << std::hex << tex_id; + ss >> tex_id_int; + std::list<std::string>::iterator texIter = texList.begin(); + for (int i=0; i<tex_id_int; i++) { + assert (texIter!=texList.end()); + texIter++; + } + output((*texIter).c_str()); + output(",{"); + printCuobjdumpOperand(®, "", ""); + output(",_,_,_};"); + } + else if(strcmp(m_base, "EXIT")==0) { + printCuobjdumpPredicate(); + output("exit"); + output(";"); + } + else if(strcmp(m_base, "GRED")==0) { + printCuobjdumpPredicate(); + // ptx instruction atom can be used to perform reduction using destination register '_' + output("atom.global"); + printCuobjdumpBaseModifiers(); + printCuobjdumpTypeModifiers(); + output(" _, "); + printCuobjdumpOperands(); + output(";"); + } else if(strcmp(m_base, "GATOM")==0) { + printCuobjdumpPredicate(); + output("atom.global"); + printCuobjdumpBaseModifiers(); + printCuobjdumpTypeModifiers(); + + printCuobjdumpOperands(); + output(";"); + }else if(strcmp(m_base, "PBK")==0) { + //PKB specifies the target of later BRK (break) instructions + // Here we convert it to nop and store the target + output("nop;"); + breaktarget = m_operands->getListStart()->stringText; + } else if(strcmp(m_base, "BRK")==0) { + printCuobjdumpPredicate(); + /* + * Convert it **at compile time** to a branch to the break target saved earlier + * Correct operation not guaranteed + */ + + output("bra "); + output(breaktarget.c_str()); + output(";"); + } else if(strcmp(m_base, "C2R")==0) { + printCuobjdumpPredicate(); + output("mov.u32"); + printCuobjdumpOperands(); + output(";"); + } else if(strcmp(m_base, "R2C")==0) { + printCuobjdumpPredicate(); + output("mov.pred"); + printCuobjdumpOperands(); + output(";"); + } + else + { + printf("Unknown Instruction: "); + printf(m_base); + printf("\n"); + output("Unknown Instruction: "); + output(m_base); + assert(0); + } + +} + diff --git a/cuobjdump_to_ptxplus/cuobjdumpInst.h b/cuobjdump_to_ptxplus/cuobjdumpInst.h new file mode 100644 index 0000000..20d31be --- /dev/null +++ b/cuobjdump_to_ptxplus/cuobjdumpInst.h @@ -0,0 +1,22 @@ +#include "decudaInstList.h" + +class cuobjdumpInst: public decudaInst +{ + +public: + //Constructor + cuobjdumpInst(); + + bool checkCubojdumpLabel(std::list<std::string> labelList, std::string label); + + void printCuobjdumpLabel(std::list<std::string> labelList); + void printCuobjdumpPredicate(); + void printCuobjdumpTypeModifiers(); + void printCuobjdumpBaseModifiers(); + void printCuobjdumpOperand(stringListPiece* currentPiece, std::string operandDelimiter, const char* base); + void printCuobjdumpOperandlohi(std::string op); + void printCuobjdumpOperands(); + + void printCuobjdumpPtxPlus(std::list<std::string> labelList, std::list<std::string> texList); +}; + diff --git a/cuobjdump_to_ptxplus/cuobjdumpInstList.cc b/cuobjdump_to_ptxplus/cuobjdumpInstList.cc new file mode 100644 index 0000000..5eaf67f --- /dev/null +++ b/cuobjdump_to_ptxplus/cuobjdumpInstList.cc @@ -0,0 +1,553 @@ +#include <iostream> +#include "cuobjdumpInstList.h" + +extern void output(const char * text); + +//Constructor +cuobjdumpInstList::cuobjdumpInstList() +{ + //initilize everything to empty +} + + + + +//TODO: Some register processing work is supposed to be done here. +void cuobjdumpInstList::addCuobjdumpRegister(std::string reg, bool lo) +{ + int vectorFlag = 0; + char * regString; + regString = new char [reg.size()+1]; + + stringList* typeModifiers = getListEnd().getTypeModifiers(); + const char* baseInst = getListEnd().getBase(); + + //TODO: support for 64bit vectors and 128bit vectors + if((strcmp(baseInst, "DADD")==0) || (strcmp(baseInst, "DMUL")==0) || (strcmp(baseInst, "DFMA")==0) || + ((typeModifiers->getSize()==1) && + (strcmp((typeModifiers->getListStart()->stringText), ".S64")==0) && + ((strcmp(baseInst, "G2R")==0)||(strcmp(baseInst, "R2G")==0)|| + (strcmp(baseInst, "GLD")==0)||(strcmp(baseInst, "GST")==0)|| + (strcmp(baseInst, "LST")==0)))) + { + vectorFlag = 64; + } + else if((typeModifiers->getSize()==1) && (strcmp((typeModifiers->getListStart()->stringText), ".S128")==0)) + { + vectorFlag = 128; + } + + //TODO: does the vector flag ever need to be set? + std::string parsedReg = parseCuobjdumpRegister(reg, lo, vectorFlag); + + strcpy(regString, parsedReg.c_str()); + + getListEnd().addOperand(regString); +} + +// add memory operand +// memType: 0=constant, 1=shared, 2=global, 3=local +int currconstmem =1; +void cuobjdumpInstList::addCuobjdumpMemoryOperand(std::string mem, int memType) { + std::string origMem = mem; + bool neg = false; + + // If constant memory type, add prefix for entry specific constant memory + if(memType == 0) { + // Global memory c14 + // Replace this with the actual global memory name + if(mem.substr(0,1) == "-") { + //Remove minus sign if exists + mem = mem.substr(1, mem.size()-1); + neg = true; + } + + if(mem.substr(0, 7) == "c [0xe]") { + // Find the global memory identifier based on the offset provided + int offset; + sscanf(mem.substr(9,mem.size()-10).c_str(), "%x", &offset); + // Find memory + bool found = false; + std::list<globalMemory>::iterator g; + for(g=m_globalMemoryList.begin(); g!=m_globalMemoryList.end(); ++g) { + if(g->offset == offset) { + mem = g->name; + found = true; + break; + } + } + + if(!found) { + printf("Could not find a global memory with this offset in: %s\n", mem.c_str()); + output("Could not find a global memory with this offset.\n"); + assert(0); + } + + } + else if(mem.substr(0, 7) == "c [0x0]"){ + mem = "constant0" + mem.substr(7, mem.length()); + } + else if(mem.substr(0, 5) == "c [0x"){ + if(currconstmem != m_entryList.size()) currconstmem++; + std::string out; + out = "constant1" + m_entryList.back().m_entryName + mem.substr(8); + mem = out.c_str(); + } + else { + output("Unrecognized memory type:"); + output(mem.c_str()); + output("\n"); + assert(0); + } + + if (neg) { + mem = "-"+mem; + } + } + + // Local memory + if(memType == 3) { + std::stringstream out; + printf("Trying to find lmem for: %s\n", m_entryList.back().m_entryName.c_str()); + printf("Original memory: %s\n", mem.c_str()); + assert(kernellmemmap[m_entryList.back().m_entryName] !=0 ); + out << "l" << kernellmemmap[m_entryList.back().m_entryName];// << mem; + mem = out.str(); + } + + // Add the memory operand to instruction operand list + char* memName = new char [strlen(mem.c_str())+1]; + strcpy(memName, mem.c_str()); + getListEnd().addOperand(memName); +} + +// increment register list and parse register +std::string cuobjdumpInstList::parseCuobjdumpRegister(std::string reg, bool lo, int vectorFlag) +{ + std::string origReg = reg; + // Make sure entry list is not empty + if(m_entryList.size() == 0) { + output("ERROR: Adding a register before adding an entry.\n"); + assert(0); + } + + // remove minus sign if exists + if(reg.substr(0,1) == "-") + reg = reg.substr(1, reg.size()-1); + + // if lo or hi register, get register name only (remove 'H' or 'L') + if(lo) + reg = reg.substr(0, reg.size()-1); + + // Increase register number if needed + // Two types of registers, R# or A# + if(reg.substr(0, 1) == "R") { + reg = reg.substr(1, reg.size()-1); + int regNum = atoi(reg.c_str()); + + // Remove register overlap at 64 + // TODO: is this still needed? + /*if(regNum > 63 && regNum < 124) { + regNum -= 64; + // Fix the origReg string + std::stringstream out; + out << ((origReg.substr(0,1)=="-") ? "-" : "") + << "$r" << regNum + << (lo ? origReg.substr(origReg.size()-3, 3) : ""); + origReg = out.str(); + }*/ + + if(vectorFlag==64) + regNum += 1; + if(vectorFlag==128) + regNum += 3; + + if( m_entryList.back().m_largestRegIndex < regNum && regNum < 124 ) + m_entryList.back().m_largestRegIndex = regNum; + else if( regNum == 124 ) + m_entryList.back().m_reg124 = true; + } else if(reg.substr(0, 1) == "A") { + reg = reg.substr(1, reg.size()-1); + int regNum = atoi(reg.c_str()); + + if( m_entryList.back().m_largestOfsRegIndex < regNum && regNum < 124 ) + m_entryList.back().m_largestOfsRegIndex = regNum; + } else if(reg == "o [0x7f]") { + m_entryList.back().m_oreg127 = true; + } else if (reg.substr(0,3) == "SR_") { + if(reg.substr(3,3)=="Tid") { + origReg = "%%tid"; + if(reg.substr(7,1)=="X") { + origReg += ".x"; + } + } + } else { + output("ERROR: unknown register type.\n"); + printf("\nERROR: unknown register type: "); + printf(reg.c_str()); + printf("\n"); + assert(0); + } + return origReg; +} + +// pred|reg double operand +void cuobjdumpInstList::addCuobjdumpDoublePredReg(std::string pred, std::string reg, bool lo) +{ + std::string parsedPred = parseCuobjdumpPredicate(pred); + std::string parsedReg = parseCuobjdumpRegister(reg, lo, 0); + + std::string doublePredReg; + if( + strcmp(getListEnd().getBase(), "DSET")==0 || + strcmp(getListEnd().getBase(), "FSET")==0 || + strcmp(getListEnd().getBase(), "ISET")==0 + ) + doublePredReg = parsedPred + "/" + parsedReg; + else + doublePredReg = parsedPred + "|" + parsedReg; + + char* doublePredRegName = new char [strlen(doublePredReg.c_str())]; + strcpy(doublePredRegName, doublePredReg.c_str()); + getListEnd().addOperand(doublePredRegName); +} + +std::string cuobjdumpInstList::parseCuobjdumpPredicate(std::string pred) +{ + std::string origPred = pred; + + // Make sure entry list is not empty + if(m_entryList.size() == 0) { + output("ERROR: Adding a predicate before adding an entry.\n"); + assert(0); + } + + // increase predicate numbers if needed + pred = pred.substr(2, pred.size()-2); + int predNum = atoi(pred.c_str()); + if( m_entryList.back().m_largestPredIndex < predNum ) + m_entryList.back().m_largestPredIndex = predNum; + + return origPred; +} + +void cuobjdumpInstList::addCubojdumpLabel(std::string label) +{ + + if(!(m_entryList.back().m_labelList.empty())) + { + std::list<std::string>::iterator labelIterator; + + for( labelIterator=m_entryList.back().m_labelList.begin(); labelIterator!=m_entryList.back().m_labelList.end(); labelIterator++ ) + { + if(label.compare(*labelIterator) == 0) + return; + } + } + + m_entryList.back().m_labelList.push_back(label); +} + +void cuobjdumpInstList::setConstMemoryMap(const char* kernelname, int index){ + std::string kernel = kernelname; + kernel = kernel.substr(14, kernel.length()-1); + kernel = kernel.substr(0, kernel.find("\t")); + printf("Setting kernelcmemmap[%s]=%d\n", kernel.c_str(), index); + kernelcmemmap[kernel] = index; +} + +void cuobjdumpInstList::setLocalMemoryMap(const char* kernelname, int index){ + std::string kernel = kernelname; + kernel = kernel.substr(10, kernel.length()-1); + kernel = kernel.substr(0, kernel.find("\t")); + printf("Setting kernellmemmap[%s]=%d\n", kernel.c_str(), index); + kernellmemmap[kernel] = index; +} + + +//NOT USED +void cuobjdumpInstList::reverseConstMemory() { + int total = kernelcmemmap.size(); + for ( std::map<std::string,int>::iterator iter = kernelcmemmap.begin(); + iter != kernelcmemmap.end(); + iter++){ + (*iter).second = total - (*iter).second; + } +} + + +// create new entry specific constant memory "bank" +void cuobjdumpInstList::addEntryConstMemory(int index, int entryIndex) +{ + constMemory newConstMem; + newConstMem.index = index; + newConstMem.entryIndex = entryIndex; + m_constMemoryList.push_back(newConstMem); +} + +void cuobjdumpInstList::addEntryConstMemory2(char* kernelname) +{ + std::string kernel = kernelname; + kernel = kernel.substr(14, kernel.length()-1); + kernel = kernel.substr(0, kernel.find("\t")); + constMemory2 newConstMem2; + newConstMem2.kernel = strdup(kernel.c_str()); + m_constMemoryList2.push_back(newConstMem2); +} + +void cuobjdumpInstList::addEntryLocalMemory(int value, int entryIndex) +{ + localMemory newLocalMem; + newLocalMem.value = value; + newLocalMem.entryIndex = entryIndex; + m_localMemoryList.push_back(newLocalMem); +} + + +// Read in constant memory from bin file +// Two cases of constant memory have been noticed so far +// 1 - All the constant memory is initialized in original ptx file. The assembler combines all this memory into c0 +// 2 - Constant memory is declared in ptx, but not initialized (initialized by host). The assembler still calls this c0 +void cuobjdumpInstList::readConstMemoryFromElfFile(std::string elf) +{ + unsigned k=1; + printf("Trying to find constant memory in elf file:\n"); + + // Get each constant segment + const boost::regex constPattern("^\\.nv\\.constant1\\.[^\n]+\n[ x0-9a-f\t]+$"); + // Parse each constseg + const boost::sregex_token_iterator end; + for ( + boost::sregex_token_iterator i(elf.begin(),elf.end(), constPattern); + i != end; + ++i + ) + { + std::string memseg = *i; + boost::smatch memResult; + + const boost::regex memValuePattern("(0x[A-Fa-f0-9]{8,8})"); + + bool memExists = boost::regex_search(memseg, memResult, memValuePattern); + + + std::list<std::string> c1; + std::list<std::string>::iterator it = c1.begin(); + + const boost::sregex_token_iterator end2; + for ( + boost::sregex_token_iterator j(memseg.begin(),memseg.end(), memValuePattern); + j != end2; + ++j ){ + c1.insert(it, *j); + } + + addEntryConstMemory(1, k); + setConstMemoryType(".u32"); + + std::list<std::string>::iterator c; + if(c1.size() > 0) { + for(c=c1.begin(); c!=c1.end(); ++c) { + std::string a = *c; + //printf("%s ", a.c_str()); + addConstMemoryValue(a); + } + } + + + printf("Found constant memory\n"); + printf(memseg.c_str()); + printf("\n"); + k++; + } + m_kernelCount = k-1; +} +void cuobjdumpInstList::setKernelCount(int k){ + m_kernelCount = k; +} +void cuobjdumpInstList::readOtherConstMemoryFromBinFile(std::string binString) +{ + // Initialize a list to store memory values + // std::list<std::string> c0; + + // Get each code segment + //const boost::regex codePattern("(code \\{[^\\{\\}]*(const \\{[^\\{\\}]*(mem \\{[^\\{\\}]*\\}[^\\{\\}]*)+\\}[^\\{\\}]*)+bincode \\{[^\\{\\}]*\\}[^\\{\\}]*\\})"); + const boost::regex codePattern("(code \\{[^\\{\\}]*(const \\{[^\\{\\}]*(mem \\{[^\\{\\}]*\\}[^\\{\\}]*)+\\}[^\\{\\}]*)*bincode \\{[^\\{\\}]*\\}[^\\{\\}]*\\})"); + + int k=1; + + // Parse each codeseg + const boost::sregex_token_iterator end; + for( + boost::sregex_token_iterator i(binString.begin(),binString.end(), codePattern); + i != end; + ++i + ) + { + std::list<std::string> c1; + + // For each code segment, get the seg numbers and memory values string + std::string codeSeg_s = *i; + std::string segnum_s, lmem_s, mem; + int segnum; + int lmem; + + boost::smatch segnumResult; + boost::smatch lmemResult; + boost::smatch memResult; + + const boost::regex segnumPattern("segnum\\s*=\\s(\\d*)"); + const boost::regex lmemPattern("lmem\\s*=\\s(\\d*)"); + const boost::regex memPattern("mem \\{([^\\}]*)\\}"); + + boost::regex_search(codeSeg_s, segnumResult, segnumPattern); + boost::regex_search(codeSeg_s, lmemResult, lmemPattern); + bool memExists = boost::regex_search(codeSeg_s, memResult, memPattern); + + lmem_s = lmemResult[1]; + lmem = atoi(lmem_s.c_str()); + + addEntryLocalMemory(lmem, k); + + if(memExists) + { + segnum_s = segnumResult[1]; + segnum = atoi(segnum_s.c_str()); + + mem = memResult[1]; + const boost::regex memValuePattern("(0x[A-Fa-f0-9]{8,8})"); + + std::list<std::string>::iterator it = c1.begin(); + + const boost::sregex_token_iterator end2; + for ( + boost::sregex_token_iterator j(mem.begin(),mem.end(), memValuePattern); + j != end2; + ++j + ) + { + c1.insert(it, *j); + } + + addEntryConstMemory(segnum, k); + setConstMemoryType(".u32"); + + std::list<std::string>::iterator c; + if(c1.size() > 0) { + for(c=c1.begin(); c!=c1.end(); ++c) { + std::string a = *c; + //printf("%s ", a.c_str()); + addConstMemoryValue(a); + } + } + } + k++; + } + m_kernelCount = k-1; +} + +void cuobjdumpInstList::printCuobjdumpInstList() +{ + // Each entry + std::list<decudaEntry>::iterator e; + for(e=m_entryList.begin(); e!=m_entryList.end(); ++e) { + + + + + for( std::list<decudaInst>::iterator currentInst=e->m_instList.begin(); + currentInst!=e->m_instList.end(); + ++currentInst) { + // Output the instruction + output("\t"); + currentInst->printDecudaInst(); + output("\n"); + } + } +} + +void cuobjdumpInstList::printCuobjdumpLocalMemory() +{ + for( std::list<localMemory>::iterator i=m_localMemoryList.begin(); + i!=m_localMemoryList.end(); + ++i) { + char line[40]; + //if(i->value > 0) + { + sprintf(line, ".local .b8 l%d[%d];\n", i->entryIndex, i->value); + output(line); + } + } +} + +void cuobjdumpInstList::printCuobjdumpPtxPlusList(cuobjdumpInstList* headerInfo) +{ + output("\n"); + printMemory(); + printCuobjdumpLocalMemory(); + // Each entry + std::list<decudaEntry>::reverse_iterator e; + for(e=m_entryList.rbegin(); e!=m_entryList.rend(); ++e) { + + output("\n"); + + // Output the header information for this entry using headerInfo + // First, find the matching entry in headerInfo + decudaEntry headerEntry; + + if( headerInfo->findEntry(e->m_entryName, headerEntry) ) { + // Entry for current header found, print it out + std::list<decudaInst>::iterator headerInstIter; + for(headerInstIter=headerEntry.m_instList.begin(); + headerInstIter!=headerEntry.m_instList.end(); + ++headerInstIter) { + if(headerInstIter!=headerEntry.m_instList.begin()) { + output("\t"); + } + headerInstIter->printHeaderPtx(); + output("\n"); + } + output("{\n"); + } else { + // Couldn't find this entry in ptx file + // Check if it is a dummy entry + if(e->m_entryName == "__cuda_dummy_entry__") { + output(".entry "); + output("__cuda_dummy_entry__"); + output("\n"); + output("{\n"); + } else { + output("Mismatch in entry names between decuda output and original ptx file.\n"); + assert(0); + } + } + assert( &*e != NULL); + printRegNames(*e); + printPredNames(*e); + printOutOfBoundRegisters(*e); + output("\n"); + + for(std::list<decudaInst>::iterator currentInst=e->m_instList.begin(); currentInst!=e->m_instList.end(); ++currentInst){ + // Output the instruction + //cuobjdumpInst* outputInst = &*currentInst; + cuobjdumpInst* outputInst = static_cast<cuobjdumpInst*>(&*currentInst); + output("\t"); + //outputInst->printCuobjdumpPtxPlus(m_entryList.back().m_labelList); + outputInst->printCuobjdumpPtxPlus(e->m_labelList, this->m_realTexList); + output("\n"); + } + output("\n\tl_exit: exit;\n"); + output("}\n"); + } +} + +void cuobjdumpInstList::addConstMemoryPtr(const char* offset, const char* size, const char* name){ + constMemoryPtr ptr; + ptr.offset = atoi(offset); + ptr.bytes = atoi(size); + ptr.name = name; + ptr.destination = "constant0"; + m_constMemoryPtrList.push_back(ptr); + printf("\naddConstMemoryPtr: %s, size: %d, offset: %d\n", ptr.name.c_str(), ptr.bytes, ptr.offset); +} + diff --git a/cuobjdump_to_ptxplus/cuobjdumpInstList.h b/cuobjdump_to_ptxplus/cuobjdumpInstList.h new file mode 100644 index 0000000..1bc8f10 --- /dev/null +++ b/cuobjdump_to_ptxplus/cuobjdumpInstList.h @@ -0,0 +1,47 @@ +#include "cuobjdumpInst.h" + +// Used for local memory segments +struct localMemory +{ + int value; + int entryIndex; +}; + +class cuobjdumpInstList: public decudaInstList +{ +protected: + std::string parseCuobjdumpPredicate(std::string pred); + int m_kernelCount; + std::map<std::string,int>kernelcmemmap; + std::map<std::string,int>kernellmemmap; + std::list<localMemory> m_localMemoryList; + +public: + //Constructor + cuobjdumpInstList(); + + void setKernelCount(int k); + void readConstMemoryFromElfFile(std::string elf); + + void addCuobjdumpRegister(std::string reg, bool lo=false); //add register + void addCuobjdumpMemoryOperand(std::string mem, int memType); + std::string parseCuobjdumpRegister(std::string reg, bool lo, int vectorFlag); + void addCuobjdumpDoublePredReg(std::string pred, std::string reg, bool lo=false); + + void addCubojdumpLabel(std::string label); + + void addEntryConstMemory(int index, int entryIndex); + void addEntryConstMemory2(char* kernel); + void addConstMemoryPtr(const char* bytes, const char* offset, const char* name); + void setConstMemoryMap(const char* kernelname, int index); + void setLocalMemoryMap(const char* kernelname, int index); + void reverseConstMemory(); + void addEntryLocalMemory(int value, int entryIndex); + void readOtherConstMemoryFromBinFile(std::string binString); // read in constant memory from bin file + + void printCuobjdumpLocalMemory(); + + void printCuobjdumpInstList(); + void printCuobjdumpPtxPlusList(cuobjdumpInstList* headerInfo); +}; + diff --git a/cuobjdump_to_ptxplus/cuobjdump_to_ptxplus.cc b/cuobjdump_to_ptxplus/cuobjdump_to_ptxplus.cc new file mode 100644 index 0000000..e8d45ef --- /dev/null +++ b/cuobjdump_to_ptxplus/cuobjdump_to_ptxplus.cc @@ -0,0 +1,162 @@ +#include <iostream> +#include "cuobjdumpInstList.h" +#include <stdio.h> +#include <fstream> + +using namespace std; + +cuobjdumpInstList *g_instList = new cuobjdumpInstList(); +cuobjdumpInstList *g_headerList = new cuobjdumpInstList(); + +int sass_parse(); +extern "C" FILE *sass_in; + +int ptx_parse(); +extern "C" FILE *ptx_in; + +int elf_parse(); +extern "C" FILE *elf_in; + +extern int g_error_detected; + +FILE *bin_in; +FILE *ptxplus_out; + +void output(const char * text) +{ + printf(text); + fprintf(ptxplus_out, text); +} + +std::string fileToString(const char * fileName) { + ifstream fileStream(fileName, ios::in); + string text, line; + while(getline(fileStream,line)) { + text += (line + "\n"); + } + fileStream.close(); + return text; +} + +std::string extractFilename( const std::string& path ) +{ + return path.substr( path.find_last_of( '/' ) +1 ); +} +int main(int argc, char* argv[]) +{ + //TODO: Output to file not yet supported. + if(argc != 5) + { + cout << "Usage: cuobjdump_to_ptxplus ptxfile sassfile elffile ptxplusfile(output)\n"; + return 0; + } + int result; + string ptxfile = argv[1]; + string sassfile = argv[2]; + string elffile = argv[3]; + string ptxplusfile = argv[4]; + + /* + char commandline[1024]; + + snprintf(commandline,1024,"cuobjdump -ptx %s > %s.ptx", exefile.c_str(), basefilename.c_str()); + fflush(stdout); + result = system(commandline); + if (result) {printf("ERROR: could not execute %s\n", commandline); exit(1);} + + + snprintf(commandline,1024,"sed '/arch\\ =\\ sm_20/,/1a$/d' %s.ptx > %s.stripped2.ptx", basefilename.c_str(), basefilename.c_str()); + fflush(stdout); + result = system(commandline); + if (result) {printf("ERROR: could not execute %s\n", commandline); exit(1);} + + snprintf(commandline,1024,"grep -v \"^arch\\ =\\|Fatbin\\ \\|^code\\ version\\|===========\\|producer\\ =\\|host\\ =\\|compile_size\\ =\\|identifier\\ =\" %s.stripped2.ptx > %s.stripped.ptx", basefilename.c_str(), basefilename.c_str()); + fflush(stdout); + result = system(commandline); + if (result) {printf("ERROR: could not execute %s\n", commandline); exit(1);} + + snprintf(commandline,1024,"cuobjdump -sass %s > %s.sass", exefile.c_str(), basefilename.c_str()); + fflush(stdout); + result = system(commandline); + if (result) {printf("ERROR: could not execute %s\n", commandline); exit(1);} + + snprintf(commandline,1024,"sed '/arch\\ =\\ sm_20/,/1a$/d' %s.sass > %s.stripped.sass", basefilename.c_str(), basefilename.c_str()); + fflush(stdout); + result = system(commandline); + if (result) {printf("ERROR: could not execute %s\n", commandline); exit(1);} + + snprintf(commandline,1024,"cuobjdump -elf %s > %s.elf", exefile.c_str(), basefilename.c_str()); + fflush(stdout); + result = system(commandline); + if (result) {printf("ERROR: could not execute %s\n", commandline); exit(1);} + + snprintf(commandline,1024,"sed '/arch\\ =\\ sm_20/,/1a$/d' %s.elf > %s.stripped.elf", basefilename.c_str(), basefilename.c_str()); + fflush(stdout); + result = system(commandline); + if (result) {printf("ERROR: could not execute %s\n", commandline); exit(1);} + */ + + sass_in = fopen(sassfile.c_str(), "r" ); + ptx_in = fopen(ptxfile.c_str(), "r" ); + elf_in = fopen(elffile.c_str(), "r"); + ptxplus_out = fopen(ptxplusfile.c_str(), "w" ); + + + std::string elf = fileToString(elffile.c_str()); + + printf("RUNNING cuobjdump_to_ptxplus ...\n"); + + + printf("Parsing .elf file %s\n", elffile.c_str()); + elf_parse(); + printf("Finished parsing .elf file %s\n", elffile.c_str()); + + //Parse original ptx + printf("Parsing .ptx file %s\n", ptxfile.c_str()); + ptx_parse(); + if (g_error_detected){ + assert(0 && "ptx parsing failed"); + } + printf("Finished parsing .ptx file %s\n", ptxfile.c_str()); + + // Copy real tex list from ptx to ptxplus instruction list + g_instList->setRealTexList(g_headerList->getRealTexList()); + // Insert constant memory from bin file +// g_instList->readConstMemoryFromElfFile(elf); +// g_instList->readOtherConstMemoryFromBinFile(fileToString(binFilename)); + + // Insert global memory from bin file +// g_instList->readGlobalMemoryFromBinFile(fileToString(binFilename)); + + // Parse cuobjdump output + printf("Parsing .sass file %s\n", sassfile.c_str()); + sass_parse(); + printf("Finished parsing .sass file %s\n", sassfile.c_str()); + /* + printf("################################################## Instruction List dump\n"); + g_instList->printCuobjdumpInstList(); + printf("################################################## END Instruction List dump\n"); + printf("################################################## Header Instructions Dump\n"); + g_headerList->printCuobjdumpInstList(); + printf("################################################## END Header Instructions Dump\n"); + */ + // Print ptxplus + output("//HEADER\n"); + g_headerList->printHeaderInstList(); + output("//END HEADER\n\n\n"); + output("//INSTRUCTIONS\n"); + g_instList->printCuobjdumpPtxPlusList(g_headerList); + output("//END INSTRUCTIONS\n"); + // TODO: remove this. Prints recorded cuobjdump output. +// g_instList->printCuobjdumpInstList(); + + fclose(sass_in); + fclose(ptx_in); +// fclose(bin_in); + fclose(ptxplus_out); + + printf("DONE. \n"); + + return 0; +} + diff --git a/cuobjdump_to_ptxplus/elf.l b/cuobjdump_to_ptxplus/elf.l new file mode 100644 index 0000000..3457a7a --- /dev/null +++ b/cuobjdump_to_ptxplus/elf.l @@ -0,0 +1,114 @@ + /*Lex file for elf files output by cuobjdump*/ +%{ +#include <stdio.h> +#include <string.h> +#include "elf_parser.hpp" + +#define yylval elf_lval + +void elf_error(const char*); +%} + +%option stack +%option noyywrap +%option yylineno + +%x cmem +%x symtab + +whitespace [ \t] +newline [\n] +notnewline [^\n] +newlines {newline}+ +ident [[:alnum:]_\.] +hexdigit [[:digit:]abcdef] +%% + +<cmem,INITIAL>\.nv\.constant1\.{notnewline}*{newline} { + BEGIN(cmem); + yylval.string_value = strdup(yytext); + return C1BEGIN; +} + +<cmem,INITIAL>\.nv\.local{notnewline}*{newline} { + BEGIN(INITIAL); + yylval.string_value = strdup(yytext); + return LOCALMEM; +} + +<cmem,INITIAL>\.nv\.constant0{notnewline}*{newline} { + BEGIN(cmem); + return C0BEGIN; +} + + +\.section" "\.symtab\tSYMTAB{newline} { + BEGIN(symtab); + return STBEGIN; +} + +\.section{notnewline}*{newline} { + //These are the lines before the symtab +} + +<cmem,INITIAL>\.{notnewline}*{newline} { + BEGIN(INITIAL); +} + +{notnewline}*{newline} { + //printf("Discarding line %s", yytext); +} + +<cmem>" "{newline}? { + //printf("#SPACE#"); + return SPACE2; +} + +<cmem>0x[0-9a-fA-F]{8} { + //printf("CMEM VAL: %s \n", yytext); + yylval.string_value = strdup(yytext); + return CMEMVAL; +} + +<symtab>{whitespace}*[[:alpha:]]+{whitespace}+[[:alpha:]]+{whitespace}+[[:alpha:]]+{whitespace}+[[:alpha:]]+{whitespace}+[[:alpha:]]+{whitespace}+[[:alpha:]]+{whitespace}+[[:alpha:]]+{whitespace}+{newline} { + return STHEADER; +} + +<symtab>{whitespace}+ {} + +<symtab>{newline} {} + +<symtab>{hexdigit}+ { + yylval.string_value = strdup(yytext); + return NUMBER; +} + +<symtab>{ident}+ { + yylval.string_value = strdup(yytext); + return IDENTIFIER; +} + +<symtab>{newline}{whitespace}*{newline}{whitespace}* { + BEGIN(INITIAL); +} + /*Reached end of file*/ +<<EOF>> return 0; + + /*No other rule matched. Throw an error*/ +. elf_error("Invalid token"); + +%% +void elf_error(const char* message) +{ + printf(" "); + printf(message); + printf(" near \""); + printf(yytext); + printf("\""); + printf(" on line "); + char line[5]; + sprintf(line, "%i", yylineno); + printf(line); + printf("\n"); + abort(); +} diff --git a/cuobjdump_to_ptxplus/elf.y b/cuobjdump_to_ptxplus/elf.y new file mode 100644 index 0000000..8f5163e --- /dev/null +++ b/cuobjdump_to_ptxplus/elf.y @@ -0,0 +1,81 @@ + /*Yacc file for elf files output by cuobjdump*/ +%{ +#include <stdio.h> +#include "cuobjdumpInstList.h" + +int yylex(void); +void yyerror(const char*); +//void addEntryConstMemory(int, int); +//void setConstMemoryType(const char*); +//void addConstMemoryValue(const char*); +extern cuobjdumpInstList *g_instList; +int cmemcount=1; +int lmemcount=1; +bool lastcmem = false;// false = constrant0, true = constant1 +%} +%union { + char* string_value; +} +%token <string_value> C1BEGIN CMEMVAL SPACE2 C0BEGIN STBEGIN STHEADER +%token <string_value> NUMBER HEXNUMBER IDENTIFIER LOCALMEM + +%% + +elffile : symtab program + ; + +symtab : STBEGIN STHEADER stcontent + ; + +stcontent : stcontent stline + | stline; + +stline : NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER IDENTIFIER { + if (strcmp($4, "11")==0) { + g_instList->addConstMemoryPtr($2, $3, $7); + } + } + | NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER {} + ; + +program : program cmemsection + | program localmemsection + | { + g_instList->setKernelCount(cmemcount-1); + //g_instList->reverseConstMemory(); + }; + +localmemsection : LOCALMEM { + printf("Found LocalMem section number %d\n", lmemcount); + g_instList->addEntryLocalMemory(0, lmemcount); + g_instList->setLocalMemoryMap($1, lmemcount); + lmemcount++; + }; + +cmemsection : C1BEGIN { + printf("Found ConstMem section number %d\n", cmemcount); + //g_instList->addEntryConstMemory(1, cmemcount); + g_instList->addEntryConstMemory2($1); + g_instList->setConstMemoryType2(".u32"); + //g_instList->setConstMemoryType(".u32"); + //g_instList->setConstMemoryMap($1,cmemcount); + cmemcount++; + lastcmem = true; + } cmemvals + | C0BEGIN { + printf("Found ConstMem c0 section\n"); + g_instList->addConstMemory(0); + g_instList->setConstMemoryType(".u32"); + lastcmem = false; + } cmemvals; + +cmemvals : cmemvals CMEMVAL SPACE2 { + //printf("Found ConstMem value\n"); + printf("addConstMemoryValue %s\n", $3); + if (lastcmem) + g_instList->addConstMemoryValue2($3); + else + g_instList->addConstMemoryValue($3); + } + | ; +%% diff --git a/cuobjdump_to_ptxplus/ptx_parser.h b/cuobjdump_to_ptxplus/ptx_parser.h new file mode 100644 index 0000000..5111743 --- /dev/null +++ b/cuobjdump_to_ptxplus/ptx_parser.h @@ -0,0 +1,336 @@ +#include <cstdlib> +#include <cstring> +#include <string> +#include <list> +#include <map> +#include <vector> +#include <assert.h> +#include <iostream> +#include <sstream> +#include "decudaInstList.h" +#include <string.h> + +#define NON_ARRAY_IDENTIFIER 1 +#define ARRAY_IDENTIFIER_NO_DIM 2 +#define ARRAY_IDENTIFIER 3 +#define P_DEBUG 1 +#define DPRINTF(...) \ + if(P_DEBUG) { \ + printf("(%s:%s:%u) ", __FILE__, __FUNCTION__, __LINE__); \ + printf(__VA_ARGS__); \ + printf("\n"); \ + fflush(stdout); \ + } + + +enum _memory_space_t { + undefined_space=0, + reg_space, + local_space, + shared_space, + param_space_unclassified, + param_space_kernel, /* global to all threads in a kernel : read-only */ + param_space_local, /* local to a thread : read-writable */ + const_space, + tex_space, + surf_space, + global_space, + generic_space +}; + +int g_error_detected; +const char *g_filename = ""; +int g_func_decl; + +void set_symtab( void* a ) {DPRINTF("");} +void end_function() {DPRINTF("");} +void add_directive() {DPRINTF("");} +void add_function_arg() {DPRINTF("");} +void add_instruction() {DPRINTF("");} +void add_file( unsigned a, const char *b ) {DPRINTF("");} +void add_variables() {DPRINTF("");} +void set_variable_type() {DPRINTF("");} +void add_option(int a ) {DPRINTF("");} +void add_array_initializer() {DPRINTF("");} +void add_label( const char *a ) {DPRINTF("");} +void set_return() {DPRINTF("");} +void add_opcode( int a ) {DPRINTF("");} +void add_pred( const char *a, int b, int c ) {DPRINTF("");} +void add_scalar_operand( const char *a ) {DPRINTF("%s", a);} +void add_neg_pred_operand( const char *a ) {DPRINTF("");} +void add_address_operand( const char *a, int b ) {DPRINTF("%s", a);} +void change_operand_lohi( int a ) {DPRINTF("");} +void change_double_operand_type( int a ) {DPRINTF("");} +void change_operand_neg( ) {DPRINTF("");} +void add_double_operand( const char *a, const char *b ) {DPRINTF("");} +void add_2vector_operand( const char *a, const char *b ) {DPRINTF("");} +void add_3vector_operand( const char *a, const char *b, const char *c ) {DPRINTF("");} +void add_4vector_operand( const char *a, const char *b, const char *c, const char *d ) {DPRINTF("");} +void add_builtin_operand( int a, int b ) {DPRINTF("");} +void add_memory_operand() {DPRINTF("");} +void change_memory_addr_space( const char *a ) {DPRINTF("");} +void add_literal_int( int a ) {DPRINTF("");} +void add_literal_float( float a ) {DPRINTF("");} +void add_literal_double( double a ) {DPRINTF("");} +void add_extern_spec() {DPRINTF("");} +void add_alignment_spec( int ) {DPRINTF("");} +void add_pragma( const char *a ) {DPRINTF("");} +void add_constptr(const char* identifier1, const char* identifier2, int offset) {DPRINTF("");} + +/*non-dummy stuff below this point*/ + + + +extern decudaInstList *g_headerList; + +// Global variable to track if we are currently inside a entry directive +bool inEntryDirective = false; +// Global variable to track is we are currently inside the parameter definitions for an entry +bool inParamDirective = false; + +bool inConstDirective = false; + +// Global variable to track if we are currently inside a tex directive +bool inTexDirective = false; + + +void add_identifier( const char *a, int b, unsigned c ) { + DPRINTF("name=%s", a); + if(inConstDirective){ + //g_headerList->getListEnd() + } +} + +void add_function_name( const char *headerInput ) +{ + DPRINTF("name=%s", headerInput); + char* headerInfo = (char*) headerInput; + const char* compareString = g_headerList->getListEnd().getBase(); + + if((strcmp(compareString, ".entry")==0)||(strcmp(compareString, ".func")==0)) + { + g_headerList->setLastEntryName(headerInfo); + g_headerList->getListEnd().addOperand(headerInfo); + } +} + +//void add_space_spec(int headerInput) +void add_space_spec( enum _memory_space_t spec, int value ) +{ + DPRINTF("spec=%u", spec); + decudaInst *instEntry; + static int constmemindex=1; + switch(spec) + { + case param_space_unclassified: + if(inEntryDirective && inParamDirective) { + instEntry = new decudaInst(); + instEntry->setBase(".param"); + g_headerList->add(instEntry); + } + break; + case tex_space: + inTexDirective = true; + /* + instEntry = new decudaInst(); + instEntry->setBase(".tex"); + g_headerList->add(instEntry); + */ + break; + case const_space: + if(!inEntryDirective) { + /* + inConstDirective = true; + instEntry = new decudaInst(); + instEntry->setBase(".const"); + g_headerList->add(instEntry); + */ + //g_headerList->addConstMemory(constmemindex++); + } + break; + } +} + +void add_scalar_type_spec( int headerInput ) +{ + DPRINTF(""); + const char* compareString = g_headerList->getListEnd().getBase(); + + if( (inEntryDirective && inParamDirective) || inTexDirective || inConstDirective) + { + switch(headerInput) + { + case S8_TYPE: + g_headerList->getListEnd().addBaseModifier(".s8"); + break; + case S16_TYPE: + g_headerList->getListEnd().addBaseModifier(".s16"); + break; + case S32_TYPE: + g_headerList->getListEnd().addBaseModifier(".s32"); + break; + case S64_TYPE: + g_headerList->getListEnd().addBaseModifier(".s64"); + break; + case U8_TYPE: + g_headerList->getListEnd().addBaseModifier(".u8"); + break; + case U16_TYPE: + g_headerList->getListEnd().addBaseModifier(".u16"); + break; + case U32_TYPE: + g_headerList->getListEnd().addBaseModifier(".u32"); + break; + case U64_TYPE: + g_headerList->getListEnd().addBaseModifier(".u64"); + break; + case F16_TYPE: + g_headerList->getListEnd().addBaseModifier(".f16"); + break; + case F32_TYPE: + g_headerList->getListEnd().addBaseModifier(".f32"); + break; + case F64_TYPE: + g_headerList->getListEnd().addBaseModifier(".f64"); + break; + case B8_TYPE: + g_headerList->getListEnd().addBaseModifier(".b8"); + break; + case B16_TYPE: + g_headerList->getListEnd().addBaseModifier(".b16"); + break; + case B32_TYPE: + g_headerList->getListEnd().addBaseModifier(".b32"); + break; + case B64_TYPE: + g_headerList->getListEnd().addBaseModifier(".b64"); + break; + case PRED_TYPE: + g_headerList->getListEnd().addBaseModifier(".pred"); + break; + default: + std::cout << "Unknown type spec" << "\n"; + break; + } + } +} + +//void version_header(double versionNumber) +void add_version_info( float versionNumber, unsigned ext) +{ + DPRINTF(""); + decudaInst *instEntry = new decudaInst(); + instEntry->setBase(".version"); + g_headerList->add(instEntry); + + + //convert double to char* + std::ostringstream strs; + strs << versionNumber; + char *versionNumber2 = strdup(strs.str().c_str()); + + g_headerList->getListEnd().addOperand(versionNumber2); + //g_headerList->getListEnd().addOperand("1.4"); +} + +void target_header(char* firstTarget) +{ + DPRINTF("%s", firstTarget); + decudaInst *instEntry = new decudaInst(); + instEntry->setBase(".target"); + g_headerList->add(instEntry); + + g_headerList->getListEnd().addOperand(firstTarget); +} + +void target_header2(char* firstTarget, char* secondTarget) +{ + DPRINTF("%s, %s", firstTarget, secondTarget); + decudaInst *instEntry = new decudaInst(); + instEntry->setBase(".target"); + g_headerList->add(instEntry); + + g_headerList->getListEnd().addOperand(firstTarget); + + g_headerList->getListEnd().addOperand(secondTarget); +} + +void target_header3(char* firstTarget, char* secondTarget, char* thirdTarget) +{ + DPRINTF("%s, %s, %s", firstTarget, secondTarget, thirdTarget); + decudaInst *instEntry = new decudaInst(); + instEntry->setBase(".target"); + g_headerList->add(instEntry); + + g_headerList->getListEnd().addOperand(firstTarget); + + g_headerList->getListEnd().addOperand(secondTarget); + + g_headerList->getListEnd().addOperand(thirdTarget); +} + +void start_function( int a ) +{ + DPRINTF(""); + inEntryDirective = true; +} + +void* reset_symtab() +{ + DPRINTF(""); + inEntryDirective = false; + void* a; + return a; +} + +void func_header(const char* headerBase) +{ + DPRINTF("%s", headerBase); + // If start of an entry + if((strcmp(headerBase, ".entry")==0)||(strcmp(headerBase, ".func")==0)) { + inEntryDirective = true; + g_headerList->addEntry(""); + decudaInst *instEntry = new decudaInst(); + instEntry->setBase(headerBase); + g_headerList->add(instEntry); + + } +} + +void func_header_info(const char* headerInfo) +{ + DPRINTF("%s", headerInfo); + const char* compareString = g_headerList->getListEnd().getBase(); + + if(inEntryDirective && !inTexDirective) { + g_headerList->getListEnd().addOperand(headerInfo); + // If start of parameters + if(strcmp(headerInfo,"(")==0) + inParamDirective = true; + + // If end of parameters + if(strcmp(headerInfo,")")==0) { + inParamDirective = false; + } + } else if(inTexDirective) { + g_headerList->addTex(headerInfo); + inTexDirective = false; + } else if(inConstDirective){ + + } else { + printf("Unkown header info: #%s#\n", headerInfo); + } + +} + +void func_header_info_int(const char* s, int i) +{ + DPRINTF("%s %d", s, i); + if(inEntryDirective && !inTexDirective) { + g_headerList->getListEnd().addOperand(s); + char *buff = (char*) malloc(30*sizeof(char)); + sprintf(buff, "%d", i); + assert (i>=0); + g_headerList->getListEnd().addOperand(buff); + } +} diff --git a/cuobjdump_to_ptxplus/sass.l b/cuobjdump_to_ptxplus/sass.l new file mode 100644 index 0000000..a4beeb1 --- /dev/null +++ b/cuobjdump_to_ptxplus/sass.l @@ -0,0 +1,324 @@ +%{ +#include <stdio.h> +#include "sass_parser.hpp" +#include <string.h> + + +/* Not sure if this is needed*/ +#define YY_NEVER_INTERACTIVE 1 + +#define yylval sass_lval + +void sass_error(const char*); +%} +%option noyywrap +%option yylineno + +/*Regular expresions go here*/ +alpha [a-zA-Z] +numeric [0-9] +hexalpha [A-Fa-f] +alphanum ({alpha}|{numeric}) +hexdigit ({numeric}|{hexalpha}) +whitespace [ \t] +newline [\n] +anycharbutnewline [^\n] +anychar ({newline}|{anycharbutnewline}) +pipe \| + +identifier ({alpha}({alphanum}|["_$"])*)|([_$%]({alphanum}|["_$"])+) +hexliteral 0[xX]{hexdigit}+U? +octliteral 0[0-7]+U? +binliteral 0[bB][01]+U? +decliteral ([1-9][0-9]*U?)|0U? +fltliteral [0-9]+\.[0-9]+ + +%% + /*Translation rules*/ + + /*Compiler directives*/ + + /*constant memory directives*/ + + /*guard predicate*/ + + /*label*/ + +"[" yylval.string_value = strdup(yytext); return OSQBRACKET; +"]" yylval.string_value = strdup(yytext); return CSQBRACKET; + + /*base instructions*/ +"BAR.ARV.WAIT b0, 0xfff" yylval.string_value = strdup(yytext); return BAR; +ADA yylval.string_value = strdup(yytext); return ADA; +BRA yylval.string_value = strdup(yytext); return BRA; +CAL yylval.string_value = strdup(yytext); return CAL; +COS yylval.string_value = strdup(yytext); return COS; +DADD yylval.string_value = strdup(yytext); return DADD; +DFMA yylval.string_value = strdup(yytext); return DFMA; +DMUL yylval.string_value = strdup(yytext); return DMUL; +EX2 yylval.string_value = strdup(yytext); return EX2; +F2F yylval.string_value = strdup(yytext); return F2F; +F2I yylval.string_value = strdup(yytext); return F2I; +FADD yylval.string_value = strdup(yytext); return FADD; +FADD32 yylval.string_value = strdup(yytext); return FADD32; +FADD32I yylval.string_value = strdup(yytext); return FADD32I; +FMAD yylval.string_value = strdup(yytext); return FMAD; +FMAD32I yylval.string_value = strdup(yytext); return FMAD32I; +FMUL yylval.string_value = strdup(yytext); return FMUL; +FMUL32 yylval.string_value = strdup(yytext); return FMUL32; +FMUL32I yylval.string_value = strdup(yytext); return FMUL32I; +FSET yylval.string_value = strdup(yytext); return FSET; +G2R yylval.string_value = strdup(yytext); return G2R; +GLD yylval.string_value = strdup(yytext); return GLD; +GST yylval.string_value = strdup(yytext); return GST; +I2F yylval.string_value = strdup(yytext); return I2F; +I2I yylval.string_value = strdup(yytext); return I2I; +S2R yylval.string_value = strdup(yytext); return S2R; +STS yylval.string_value = strdup(yytext); return STS; +LD yylval.string_value = strdup(yytext); return LD; +ST yylval.string_value = strdup(yytext); return ST; +IADD yylval.string_value = strdup(yytext); return IADD; +IADD32 yylval.string_value = strdup(yytext); return IADD32; +IADD32I yylval.string_value = strdup(yytext); return IADD32I; +IMAD yylval.string_value = strdup(yytext); return IMAD; +IMAD\.U24 yylval.string_value = strdup(yytext); return IMAD24; +IMAD\.S24 yylval.string_value = strdup(yytext); return IMAD24; +IMAD32 yylval.string_value = strdup(yytext); return IMAD32; +IMAD32I yylval.string_value = strdup(yytext); return IMAD32I; +IMUL yylval.string_value = strdup(yytext); return IMUL; +IMUL\.U24\.U24 yylval.string_value = strdup(yytext); return IMUL24; +IMUL\.S24\.S24 yylval.string_value = strdup(yytext); return IMULS24; +IMUL32 yylval.string_value = strdup(yytext); return IMUL32; +IMUL32\.S24\.S24 yylval.string_value = strdup(yytext); return IMUL32S24; +IMUL32\.U24\.U24 yylval.string_value = strdup(yytext); return IMUL32U24; +IMUL32I\.S24\.S24 yylval.string_value = strdup(yytext); return IMUL32IS24; +IMUL32I yylval.string_value = strdup(yytext); return IMUL32I; +IMUL32I\.U24\.U24 yylval.string_value = strdup(yytext); return IMUL32I24; +ISET yylval.string_value = strdup(yytext); return ISET; +LG2 yylval.string_value = strdup(yytext); return LG2; +LLD yylval.string_value = strdup(yytext); return LLD; +LOP\.AND yylval.string_value = strdup(yytext); return AND; +LOP\.OR yylval.string_value = strdup(yytext); return OR; +LOP\.PASS_B yylval.string_value = strdup(yytext); return NOT; +LOP\.XOR yylval.string_value = strdup(yytext); return XOR; +LOP\.S\.AND yylval.string_value = strdup(yytext); return ANDS; +LOP\.S\.OR yylval.string_value = strdup(yytext); return ORS; +LOP\.S\.PASS_B yylval.string_value = strdup(yytext); return NOTS; +LOP\.S\.XOR yylval.string_value = strdup(yytext); return XORS; +LST yylval.string_value = strdup(yytext); return LST; +MOV yylval.string_value = strdup(yytext); return MOV; +MOV32 yylval.string_value = strdup(yytext); return MOV32; +MVC yylval.string_value = strdup(yytext); return MVC; +MVI yylval.string_value = strdup(yytext); return MVI; +NOP yylval.string_value = strdup(yytext); return NOP; +R2A yylval.string_value = strdup(yytext); return R2A; +R2G yylval.string_value = strdup(yytext); return R2G; +R2G.U16.U8 yylval.string_value = strdup(yytext); return R2GU16U8; +RCP yylval.string_value = strdup(yytext); return RCP; +RCP32 yylval.string_value = strdup(yytext); return RCP32; +RET yylval.string_value = strdup(yytext); return RET; +RRO yylval.string_value = strdup(yytext); return RRO; +RSQ yylval.string_value = strdup(yytext); return RSQ; +SIN yylval.string_value = strdup(yytext); return SIN; +SHL yylval.string_value = strdup(yytext); return SHL; +SHR yylval.string_value = strdup(yytext); return SHR; +SSY yylval.string_value = strdup(yytext); return SSY; +BAR yylval.string_value = strdup(yytext); return BAR; +LDS yylval.string_value = strdup(yytext); return LDS; +IMIN yylval.string_value = strdup(yytext); return IMIN; +IMAX yylval.string_value = strdup(yytext); return IMAX; +FMAX yylval.string_value = strdup(yytext); return FMAX; +FMIN yylval.string_value = strdup(yytext); return FMIN; +C2R yylval.string_value = strdup(yytext); return C2R; +R2C yylval.string_value = strdup(yytext); return R2C; +A2R yylval.string_value = strdup(yytext); return A2R; +TEX yylval.string_value = strdup(yytext); return TEX; +TEX32 yylval.string_value = strdup(yytext); return TEX32; +EXIT yylval.string_value = strdup(yytext); return EXIT; +GRED yylval.string_value = strdup(yytext); return GRED; +GATOM yylval.string_value = strdup(yytext); return GATOM; +PBK yylval.string_value = strdup(yytext); return PBK; +BRK yylval.string_value = strdup(yytext); return BRK; + + /*instruction modifiers*/ +EQ yylval.string_value = strdup(yytext); return EQ; +EQU yylval.string_value = strdup(yytext); return EQU; +GE yylval.string_value = strdup(yytext); return GE; +GEU yylval.string_value = strdup(yytext); return GEU; +GT yylval.string_value = strdup(yytext); return GT; +GTU yylval.string_value = strdup(yytext); return GTU; +LE yylval.string_value = strdup(yytext); return LE; +LEU yylval.string_value = strdup(yytext); return LEU; +LT yylval.string_value = strdup(yytext); return LT; +LTU yylval.string_value = strdup(yytext); return LTU; +NE yylval.string_value = strdup(yytext); return NE; +NEU yylval.string_value = strdup(yytext); return NEU; +\.BEXT yylval.string_value = strdup(yytext); return DOTBEXT; +\.S yylval.string_value = strdup(yytext); return DOTS; +\.SFU yylval.string_value = strdup(yytext); return DOTSFU; +\.TRUNC yylval.string_value = strdup(yytext); return DOTTRUNC; +\.IR yylval.string_value = strdup(yytext); /*return DOTIR;*/ +\.UN yylval.string_value = strdup(yytext); return DOTUN; +\.NODEP yylval.string_value = strdup(yytext); return DOTNODEP; +\.CARRY0 yylval.string_value = strdup(yytext); return DOTCARRY0; +\.SAT yylval.string_value = strdup(yytext); + + + /* comparison operators */ +\.EQ yylval.string_value = strdup(yytext); return DOTEQ; +\.EQU yylval.string_value = strdup(yytext); return DOTEQU; +\.GE yylval.string_value = strdup(yytext); return DOTGE; +\.GEU yylval.string_value = strdup(yytext); return DOTGEU; +\.GT yylval.string_value = strdup(yytext); return DOTGT; +\.GTU yylval.string_value = strdup(yytext); return DOTGTU; +\.LE yylval.string_value = strdup(yytext); return DOTLE; +\.LEU yylval.string_value = strdup(yytext); return DOTLEU; +\.LT yylval.string_value = strdup(yytext); return DOTLT; +\.LTU yylval.string_value = strdup(yytext); return DOTLTU; +\.NE yylval.string_value = strdup(yytext); return DOTNE; +\.NEU yylval.string_value = strdup(yytext); return DOTNEU; +\.NOT_SIGN yylval.string_value = strdup(yytext); return DOTNSF; +\.SIGN yylval.string_value = strdup(yytext); return DOTSF; +\.CARRY yylval.string_value = strdup(yytext); return DOTCARRY; +\.CC yylval.string_value = strdup(yytext); return DOTCC; +\.X yylval.string_value = strdup(yytext); return DOTX; +\.E yylval.string_value = strdup(yytext); return DOTE; +\.RED yylval.string_value = strdup(yytext); return DOTRED; +\.POPC yylval.string_value = strdup(yytext); return DOTPOPC; + + /*operand types*/ +\.F16 yylval.string_value = strdup(yytext); return DOTF16; +\.F32 yylval.string_value = strdup(yytext); return DOTF32; +\.F64 yylval.string_value = strdup(yytext); return DOTF64; +\.S8 yylval.string_value = strdup(yytext); return DOTS8; +\.S16 yylval.string_value = strdup(yytext); return DOTS16; +\.S32 yylval.string_value = strdup(yytext); return DOTS32; +\.S64 yylval.string_value = strdup(yytext); return DOTS64; +\.S128 yylval.string_value = strdup(yytext); return DOTS128; +\.U8 yylval.string_value = strdup(yytext); return DOTU8; +\.U16 yylval.string_value = strdup(yytext); return DOTU16; +\.U32 yylval.string_value = strdup(yytext); return DOTU32; +\.U24 yylval.string_value = strdup(yytext); return DOTU24; +\.U64 yylval.string_value = strdup(yytext); return DOTU64; +\.HI yylval.string_value = strdup(yytext); return DOTHI; +\.NOINC yylval.string_value = strdup(yytext); return DOTNOINC; + + /*geometries*/ + + /*register operands*/ +[\-]?R{numeric}+ yylval.string_value = strdup(yytext); return REGISTER; +[\-]?R{numeric}+L yylval.string_value = strdup(yytext); return REGISTERLO; +[\-]?R{numeric}+H yylval.string_value = strdup(yytext); return REGISTERHI; +A{numeric}+ yylval.string_value = strdup(yytext); return OFFSETREGISTER; +\.C{numeric} yylval.string_value = strdup(yytext); return PREDREGISTER; +"o ["{hexliteral}\] yylval.string_value = strdup(yytext); return PREDREGISTER2; +C{numeric} yylval.string_value = strdup(yytext); return PREDREGISTER3; +"SR_"[^\.; \t]+ yylval.string_value = strdup(yytext); return SREGISTER; + + /*tex operand*/ + + /*vector operands*/ + + /*special registers*/ + + /* cuobjdump header */ +"Fatbin ptx code:" yylval.string_value = strdup(yytext); return PTXHEADER; +"Fatbin elf code:" yylval.string_value = strdup(yytext); return ELFHEADER; +"================" +"arch = " yylval.string_value = strdup(yytext); return INFOARCHVERSION; +"code version = " yylval.string_value = strdup(yytext); return INFOCODEVERSION_HEADER; +\[{numeric},{numeric}\] yylval.string_value = strdup(yytext); return INFOCODEVERSION; +"producer = " yylval.string_value = strdup(yytext); return INFOPRODUCER; +"host = " yylval.string_value = strdup(yytext); return INFOHOST; +{numeric}{numeric}"bit" yylval.string_value = strdup(yytext); return INFOCOMPILESIZE; +"compile_size = " yylval.string_value = strdup(yytext); return INFOCOMPILESIZE_HEADER; +"identifier = " yylval.string_value = strdup(yytext); return INFOIDENTIFIER; +"code for " yylval.string_value = strdup(yytext); return VERSIONHEADER; +"Function : " yylval.string_value = strdup(yytext); return FUNCTIONHEADER; +"/*"{hexliteral}{whitespace}*"*/" yylval.string_value = strdup(yytext); return INSTHEX; +"." yylval.string_value = strdup(yytext); return DOT; + + /*memory location operands*/ +[\-]?"|g| ["{hexliteral}"]"".U16"? yylval.string_value = strdup(yytext); return ABSSMEMLOCATION; +[\-]?"|g| [R"{numeric}+\]".U16"? yylval.string_value = strdup(yytext); return ABSSMEMLOCATION; +[\-]?"|g| [A"{numeric}+\+{hexliteral}\]".U16"? yylval.string_value = strdup(yytext); return ABSSMEMLOCATION; +[\-]?"|g| [A"{numeric}+\+\+\+{hexliteral}\]".U16"? yylval.string_value = strdup(yytext); return ABSSMEMLOCATION; + +[\-]?"g ["{hexliteral}"]"".U16"? yylval.string_value = strdup(yytext); return SMEMLOCATION; +[\-]?"g [R"{numeric}+\]".U16"? yylval.string_value = strdup(yytext); return SMEMLOCATION; +[\-]?"g [A"{numeric}+\+{hexliteral}\]".U16"? yylval.string_value = strdup(yytext); return SMEMLOCATION; +[\-]?"g [A"{numeric}+\+\+\+{hexliteral}\]".U16"? yylval.string_value = strdup(yytext); return SMEMLOCATION; + +[\-]?"global14 ["{hexliteral}"]"".U16"? yylval.string_value = strdup(yytext); return GMEMLOCATION; +[\-]?"global14 [R"{numeric}+\]".U16"? yylval.string_value = strdup(yytext); return GMEMLOCATION; +[\-]?"global14 [A"{numeric}+\+{hexliteral}\]".U16"? yylval.string_value = strdup(yytext); return GMEMLOCATION; +[\-]?"global14 [A"{numeric}+\+\+\+{hexliteral}\]".U16"? yylval.string_value = strdup(yytext); return GMEMLOCATION; + +[\-]?"c ["{hexliteral}"] ["{hexliteral}"]"".U16"? yylval.string_value = strdup(yytext); return CMEMLOCATION; +[\-]?"c ["{hexliteral}"] [R"{numeric}+\]".U16"? yylval.string_value = strdup(yytext); return CMEMLOCATION; +[\-]?"c ["{hexliteral}"] [A"{numeric}+\+{hexliteral}\]".U16"? yylval.string_value = strdup(yytext); return CMEMLOCATION; +[\-]?"c ["{hexliteral}"] [A"{numeric}+\+\+\+{hexliteral}\]".U16"? yylval.string_value = strdup(yytext); return CMEMLOCATION; + +[\-]?"local ["{hexliteral}"]"".U16"? yylval.string_value = strdup(yytext); return LMEMLOCATION; +[\-]?"local [R"{numeric}+\]".U16"? yylval.string_value = strdup(yytext); return LMEMLOCATION; +[\-]?"local [A"{numeric}+\+{hexliteral}\]".U16"? yylval.string_value = strdup(yytext); return LMEMLOCATION; +[\-]?"local [A"{numeric}+\+\+\+{hexliteral}\]".U16"? yylval.string_value = strdup(yytext); return LMEMLOCATION; + + /*identifier + literals*/ + +{identifier} yylval.string_value = strdup(yytext); return IDENTIFIER; +[\-]?{hexliteral} yylval.string_value = strdup(yytext); return HEXLITERAL; //change to int later? + + /*label ends*/ +"/*" yylval.string_value = strdup(yytext); return LABELSTART; +"*/" yylval.string_value = strdup(yytext); return LABELEND; +{hexdigit}{hexdigit}{hexdigit}{hexdigit} yylval.string_value = strdup(yytext); return LABEL; + + /*braces*/ + + /*brackets*/ +\( yylval.string_value = strdup(yytext); return LEFTBRACKET; +\) yylval.string_value = strdup(yytext); return RIGHTBRACKET; + + /* pound sign*/ + + /* comma*/ +"," /*yylval.string_value = strdup(yytext); return COMMA;*/ + + /* underscore sign*/ + + /* pipe*/ +"|" yylval.string_value = strdup(yytext); return PIPE; +"~" yylval.string_value = strdup(yytext); return TILDE; + + /*Need to create to newline tokens*/ +{newline}+ return NEWLINE; + + /* semicolon */ +; return SEMICOLON; + + /*discard whitespace*/ +{whitespace}+ + /*discard comments*/ +"//"{anycharbutnewline}* + /*discard dividers*/ +"-----"[\-]+ +"....."[\.]+ + + + /*reached end of file*/ +<<EOF>> return 0; + + /*None of the rules matched. Throw error*/ +. sass_error("Invalid token"); + +%% + +void sass_error(const char* message) +{ + printf(" "); printf(message); printf(" near \""); printf(yytext); printf("\""); + printf(" on line "); + char line[5]; sprintf(line, "%i", yylineno); printf(line); + printf("\n"); + exit(1); +} diff --git a/cuobjdump_to_ptxplus/sass.y b/cuobjdump_to_ptxplus/sass.y new file mode 100644 index 0000000..06d2750 --- /dev/null +++ b/cuobjdump_to_ptxplus/sass.y @@ -0,0 +1,405 @@ +%{ +#include <stdio.h> +#include "cuobjdumpInstList.h" + +int yylex(void); +void yyerror(const char*); + +extern cuobjdumpInstList *g_instList; + +cuobjdumpInst *instEntry; +%} + + +%union { + double double_value; + float float_value; + int int_value; + char * string_value; + void * ptr_value; +} + +%token <string_value> BAR +%token <string_value> ADA AND ANDS BRA CAL COS DADD DFMA DMUL EX2 F2F F2I FADD +%token <string_value> FADD32 FADD32I FMAD FMAD32I FMUL FMUL32 FMUL32I FSET G2R +%token <string_value> GLD GST I2F I2I IADD IADD32 IADD32I IMAD IMAD24 IMAD32I IMAD32 +%token <string_value> IMUL IMUL24 IMULS24 IMUL32 IMUL32S24 IMUL32U24 IMUL32I IMUL32I24 IMUL32IS24 +%token <string_value> ISET LG2 LLD LST MOV MOV32 MVC MVI NOP NOT NOTS OR ORS +%token <string_value> R2A R2G R2GU16U8 RCP RCP32 RET RRO RSQ SIN SHL SHR SSY XOR XORS +%token <string_value> S2R LD STS LDS ST IMIN IMAX A2R FMAX FMIN TEX TEX32 C2R EXIT +%token <string_value> GRED PBK BRK R2C GATOM + +%token <string_value> EQ EQU GE GEU GT GTU LE LEU LT LTU NE NEU +%token <string_value> DOTBEXT DOTS DOTSFU +%token <string_value> DOTTRUNC DOTIR DOTUN DOTNODEP DOTCARRY0 DOTSAT +%token <string_value> DOTF16 DOTF32 DOTF64 DOTS8 DOTS16 DOTS32 DOTS64 DOTS128 DOTU8 DOTU16 DOTU32 DOTU24 DOTU64 +%token <string_value> DOTHI DOTNOINC +%token <string_value> DOTEQ DOTEQU DOTGE DOTGEU DOTGT DOTGTU DOTLE DOTLEU DOTLT DOTLTU DOTNE DOTNEU DOTNSF DOTSF DOTCARRY +%token <string_value> DOTCC DOTX DOTE DOTRED DOTPOPC +%token <string_value> REGISTER REGISTERLO REGISTERHI OFFSETREGISTER +%token <string_value> PREDREGISTER PREDREGISTER2 PREDREGISTER3 SREGISTER +%token <string_value> VERSIONHEADER FUNCTIONHEADER +%token <string_value> SMEMLOCATION ABSSMEMLOCATION GMEMLOCATION CMEMLOCATION LMEMLOCATION +%token <string_value> IDENTIFIER +%token <string_value> HEXLITERAL +%token <string_value> LEFTBRACKET RIGHTBRACKET +%token <string_value> PIPE TILDE +%token <string_value> NEWLINE SEMICOLON /*COMMA*/ +%token <string_value> LABEL LABELSTART LABELEND +%token <string_value> PTXHEADER ELFHEADER +%token <string_value> INFOARCHVERSION +%token <string_value> INFOCODEVERSION_HEADER INFOCODEVERSION +%token <string_value> INFOPRODUCER +%token <string_value> INFOHOST +%token <string_value> INFOCOMPILESIZE_HEADER INFOCOMPILESIZE +%token <string_value> INFOIDENTIFIER DOT +%token <string_value> INSTHEX +%token <string_value> OSQBRACKET CSQBRACKET + /* set types for rules */ +%type<string_value> simpleInstructions +%type<string_value> predicateModifier +%type<string_value> opTypes + +%% + + /*translation rules*/ +program : NEWLINE sassCode + | program sassCode + | ; + +sassCode : VERSIONHEADER IDENTIFIER functionList { printf($1); printf($2); printf(" No parsing errors\n\n"); } + | newlines VERSIONHEADER IDENTIFIER functionList { printf($2); printf($3); printf(" No parsing errors\n\n"); } + ; + +functionList : functionList FUNCTIONHEADER IDENTIFIER { + printf($2); + printf($3); + printf("\n"); + g_instList->addEntry($3); + instEntry = new cuobjdumpInst(); + instEntry->setBase(".entry"); + g_instList->add(instEntry); + g_instList->getListEnd().addOperand($3);} statementList { /*g_instList->getListEnd().addBaseModifier(".exit");*/ } +/* | FUNCTIONHEADER IDENTIFIER { printf($1); printf($2); + g_instList->addEntry($2); + instEntry = new cuobjdumpInst(); + instEntry->setBase(".entry"); + g_instList->add(instEntry); + g_instList->getListEnd().addOperand($2);} statementList { g_instList->getListEnd().addBaseModifier(".exit"); }*/ + | functionList newlines + | + ; + +statementList : statementList statement newlines { printf("\n"); } + | statement newlines { printf("\n"); } + | statementList statement SEMICOLON newlines { printf(";\n"); } + | statement SEMICOLON newlines { printf(";\n"); } + | newlines {} + ; + +newlines : NEWLINE + | newlines NEWLINE + ; + +statement : { instEntry = new cuobjdumpInst(); } instructionLabel instructionHex assemblyInstruction + ; + +instructionHex : INSTHEX + ; + +instructionLabel : LABELSTART LABEL LABELEND { char* tempInput = $2; + char* tempLabel = new char[12]; + tempLabel[0] = 'l'; + tempLabel[1] = '0'; + tempLabel[2] = 'x'; + for(int i=0; i<(8-strlen(tempInput)); i++) + { + tempLabel[3+i] = '0'; + } + for(int i=(11-strlen(tempInput)); i<11; i++) + { + tempLabel[i] = tempInput[i-(11-strlen(tempInput))]; + } + tempLabel[11] = '\0'; + instEntry->setLabel(tempLabel); } + ; + +assemblyInstruction : baseInstruction modifierList operandList { } + /*| baseInstruction operandList { }*/ + /*| baseInstruction modifierList { }*/ + /*| baseInstruction { }*/ + ; + +baseInstruction : simpleInstructions { printf($1); instEntry->setBase($1); g_instList->add(instEntry);} + | branchInstructions + | GRED DOT simpleInstructions { printf($1); instEntry->setBase($1); g_instList->add(instEntry); g_instList->getListEnd().addBaseModifier($3);} + | GATOM DOT simpleInstructions { printf($1); instEntry->setBase($1); g_instList->add(instEntry); g_instList->getListEnd().addBaseModifier($3);} + | pbkInstruction + ; + +simpleInstructions : ADA | AND | ANDS | COS | DADD | DFMA | DMUL | EX2 | F2F + | F2I | FADD | FADD32 | FADD32I | FMAD | FMAD32I | FMUL + | FMUL32 | FMUL32I | FSET | G2R | GLD | GST | I2F | I2I + | IADD | IADD32 | IADD32I | IMAD | IMAD24 | IMAD32I | IMAD32 | IMUL + | IMUL24 | IMULS24 | IMUL32 | IMUL32S24 | IMUL32I | IMUL32I24 | IMUL32IS24 + | IMUL32U24 + | ISET | LG2 | LLD | LST | MOV | MOV32 | MVC | MVI | NOP + | NOT | NOTS | OR | ORS | R2A | R2G | R2GU16U8 | RCP | RCP32 | RET | RRO + | RSQ | SHL | SHR | SIN | SSY | XOR | XORS | S2R | LD | STS + | LDS | ST | EXIT | BAR | IMIN | IMAX | A2R | FMAX | FMIN + | TEX | TEX32 | C2R | BRK | R2C + ; + +pbkInstruction : PBK { + printf($1); instEntry->setBase($1); g_instList->add(instEntry); + } HEXLITERAL { + char* tempInput = $3; + char* tempLabel = new char[12]; + tempLabel[0] = 'l'; + tempLabel[1] = '0'; + tempLabel[2] = 'x'; + for(int i=0; i<(10-strlen(tempInput)); i++) + { + tempLabel[3+i] = '0'; + } + for(int i=(13-strlen(tempInput)); i<11; i++) + { + tempLabel[i] = tempInput[i-(11-strlen(tempInput))]; + } + tempLabel[11] = '\0'; + g_instList->getListEnd().addOperand(tempLabel); + g_instList->addCubojdumpLabel(tempLabel); + } + ; + +branchInstructions : BRA {printf($1); instEntry->setBase($1); g_instList->add(instEntry);} instructionPredicate HEXLITERAL + { printf($4); + char* tempInput = $4; + char* tempLabel = new char[12]; + tempLabel[0] = 'l'; + tempLabel[1] = '0'; + tempLabel[2] = 'x'; + for(int i=0; i<(10-strlen(tempInput)); i++) + { + tempLabel[3+i] = '0'; + } + for(int i=(13-strlen(tempInput)); i<11; i++) + { + tempLabel[i] = tempInput[i-(11-strlen(tempInput))]; + } + tempLabel[11] = '\0'; + g_instList->getListEnd().addOperand(tempLabel); + g_instList->addCubojdumpLabel(tempLabel);} + | BRA {printf($1); instEntry->setBase($1); g_instList->add(instEntry);} HEXLITERAL + { printf($3); + char* tempInput = $3; + char* tempLabel = new char[12]; + tempLabel[0] = 'l'; + tempLabel[1] = '0'; + tempLabel[2] = 'x'; + for(int i=0; i<(10-strlen(tempInput)); i++) + { + tempLabel[3+i] = '0'; + } + for(int i=(13-strlen(tempInput)); i<11; i++) + { + tempLabel[i] = tempInput[i-(11-strlen(tempInput))]; + } + tempLabel[11] = '\0'; + g_instList->getListEnd().addOperand(tempLabel); + g_instList->addCubojdumpLabel(tempLabel);} + | CAL {printf($1); instEntry->setBase($1); g_instList->add(instEntry);} HEXLITERAL + { printf($3); + char* tempInput = $3; + char* tempLabel = new char[12]; + tempLabel[0] = 'l'; + tempLabel[1] = '0'; + tempLabel[2] = 'x'; + for(int i=0; i<(10-strlen(tempInput)); i++) + { + tempLabel[3+i] = '0'; + } + for(int i=(13-strlen(tempInput)); i<11; i++) + { + tempLabel[i] = tempInput[i-(11-strlen(tempInput))]; + } + tempLabel[11] = '\0'; + g_instList->getListEnd().addOperand(tempLabel); + g_instList->addCubojdumpLabel(tempLabel);} + + | CAL {printf($1); instEntry->setBase($1); g_instList->add(instEntry);} DOTNOINC HEXLITERAL + { printf($4); + char* tempInput = $4; + char* tempLabel = new char[12]; + tempLabel[0] = 'l'; + tempLabel[1] = '0'; + tempLabel[2] = 'x'; + for(int i=0; i<(10-strlen(tempInput)); i++) + { + tempLabel[3+i] = '0'; + } + for(int i=(13-strlen(tempInput)); i<11; i++) + { + tempLabel[i] = tempInput[i-(11-strlen(tempInput))]; + } + tempLabel[11] = '\0'; + g_instList->getListEnd().addOperand(tempLabel); + g_instList->addCubojdumpLabel(tempLabel);} + + ; + +modifierList : modifier modifierList + /*| modifier */ + | + ; + +modifier : opTypes { printf($1); g_instList->getListEnd().addTypeModifier($1);} + | DOTBEXT { g_instList->getListEnd().addBaseModifier(".bext"); } + | DOTS { g_instList->getListEnd().addBaseModifier(".s"); } + | DOTSFU { g_instList->getListEnd().addBaseModifier(".sfu"); } + | DOTTRUNC { g_instList->getListEnd().addBaseModifier(".rz"); } + | DOTX { g_instList->getListEnd().addBaseModifier(".x"); } + | DOTE { g_instList->getListEnd().addBaseModifier(".e"); } + | DOTRED { g_instList->getListEnd().addBaseModifier(".red"); } + | DOTPOPC { g_instList->getListEnd().addBaseModifier(".popc"); } + | DOTIR { g_instList->getListEnd().addBaseModifier(".ir"); } + | DOTUN { /*g_instList->getListEnd().addBaseModifier(".un"); */} + | DOTNODEP { /*g_instList->getListEnd().addBaseModifier(".nodep"); */} + | DOTCARRY0 { /*g_instList->getListEnd().addBaseModifier(".carry0"); */} + ; + +opTypes : DOTF16 //{ printf($1); g_instList->getListEnd().addTypeModifier($1);} + | DOTF32 //{ printf($1); g_instList->getListEnd().addTypeModifier($1);} + | DOTF64 //{ printf($1); g_instList->getListEnd().addTypeModifier($1);} + | DOTS8 //{ printf($1); g_instList->getListEnd().addTypeModifier($1);} + | DOTS16 //{ printf($1); g_instList->getListEnd().addTypeModifier($1);} + | DOTS32 //{ printf($1); g_instList->getListEnd().addTypeModifier($1);} + | DOTS64 //{ printf($1); g_instList->getListEnd().addTypeModifier($1);} + | DOTS128 //{ printf($1); g_instList->getListEnd().addTypeModifier($1);} + | DOTU8 //{ printf($1); g_instList->getListEnd().addTypeModifier($1);} + | DOTU16 //{ printf($1); g_instList->getListEnd().addTypeModifier($1);} + | DOTU32 //{ printf($1); g_instList->getListEnd().addTypeModifier($1);} + | DOTU24 //{ printf($1); g_instList->getListEnd().addTypeModifier($1);} + | DOTU64 //{ printf($1); g_instList->getListEnd().addTypeModifier($1);} + | DOTHI //{ printf($1); g_instList->getListEnd().addTypeModifier($1);} + ; + +operandList : operandList { printf(" "); } /*COMMA*/ operand {} + /*| { printf(" "); } operand {}*/ + | + ; + +operand : registerlocation + | PIPE registerlocation PIPE { g_instList->getListEnd().addBaseModifier(".abs"); } + | TILDE registerlocation + | LEFTBRACKET instructionPredicate RIGHTBRACKET + | memorylocation opTypes { printf($2); g_instList->getListEnd().addTypeModifier($2);} + | memorylocation + | immediateValue + | extraModifier + | operandPredicate + | preOperand + ; +/* Register of the format [R0] will be converted to R0 */ +/* regMod will be also ignored */ +registerlocation : REGISTER regMod { printf($1); g_instList->addCuobjdumpRegister($1);} + | OSQBRACKET REGISTER CSQBRACKET { printf($1); printf($2); printf($3); g_instList->addCuobjdumpRegister($2);} + | REGISTERLO { printf($1); g_instList->addCuobjdumpRegister($1,true);} + | REGISTERHI { printf($1); g_instList->addCuobjdumpRegister($1,true);} + | SREGISTER { printf($1); g_instList->addCuobjdumpRegister($1,false);} + | OFFSETREGISTER { printf($1); g_instList->addCuobjdumpRegister($1);} + | PREDREGISTER PREDREGISTER2 { printf($1); printf(" "); printf($2); g_instList->addCuobjdumpDoublePredReg($1, $2);} + | PREDREGISTER REGISTER { printf($1); printf(" "); printf($2); g_instList->addCuobjdumpDoublePredReg($1, $2);} + /*| REGISTER PREDREGISTER3 { printf($1); printf(" "); printf($2); g_instList->addCuobjdumpRegister($1); printf("WEIRD CASE\n");}*/ + ; + +regMod : DOTCC + | + ; + + +memorylocation : SMEMLOCATION { printf($1); g_instList->addCuobjdumpMemoryOperand($1,1);} + | ABSSMEMLOCATION { + printf($1); + char* input = $1; + char* temp = new char[99]; + temp[0] = input[1]; + int i=1; + while (i < strlen(input)-2) { + temp[i] = input[i+2]; + i++; + } + g_instList->addCuobjdumpMemoryOperand(temp,1); + g_instList->getListEnd().addBaseModifier(".abs"); + } + | GMEMLOCATION { printf($1); g_instList->addCuobjdumpMemoryOperand($1,2);} + | CMEMLOCATION { printf($1); g_instList->addCuobjdumpMemoryOperand($1,0);} + | LMEMLOCATION { printf($1); g_instList->addCuobjdumpMemoryOperand($1,3);} + ; + +immediateValue : IDENTIFIER { printf($1); g_instList->getListEnd().addOperand($1);} + | HEXLITERAL { printf($1); g_instList->getListEnd().addOperand($1);} + ; + +extraModifier : EQ { printf($1); g_instList->getListEnd().addBaseModifier($1);} + | EQU { printf($1); g_instList->getListEnd().addBaseModifier($1);} + | GE { printf($1); g_instList->getListEnd().addBaseModifier($1);} + | GEU { printf($1); g_instList->getListEnd().addBaseModifier($1);} + | GT { printf($1); g_instList->getListEnd().addBaseModifier($1);} + | GTU { printf($1); g_instList->getListEnd().addBaseModifier($1);} + | LE { printf($1); g_instList->getListEnd().addBaseModifier($1);} + | LEU { printf($1); g_instList->getListEnd().addBaseModifier($1);} + | LT { printf($1); g_instList->getListEnd().addBaseModifier($1);} + | LTU { printf($1); g_instList->getListEnd().addBaseModifier($1);} + | NE { printf($1); g_instList->getListEnd().addBaseModifier($1);} + | NEU { printf($1); g_instList->getListEnd().addBaseModifier($1);} + ; + +instructionPredicate : PREDREGISTER3 predicateModifier {printf($1); printf($2); + g_instList->getListEnd().setPredicate($1); + g_instList->getListEnd().addPredicateModifier($2);} + | PREDREGISTER3 {printf($1); g_instList->getListEnd().setPredicate($1);} + ; + +operandPredicate : PREDREGISTER3 predicateModifier { + printf($1); + printf($2); + //g_instList->getListEnd().addOperand($1); + g_instList->getListEnd().setPredicate($1); + g_instList->getListEnd().addPredicateModifier($2); + /*May be the modifier needs to be added too*/ + } + | PREDREGISTER3 { + printf("HELLO: "); + printf($1); + g_instList->getListEnd().addOperand($1); + } + ; + + +preOperand : EX2 { printf($1); g_instList->getListEnd().addBaseModifier("ex2");} + | SIN { printf($1); g_instList->getListEnd().addBaseModifier("sin");} + | COS { printf($1); g_instList->getListEnd().addBaseModifier("cos");} + ; + +predicateModifier : DOTEQ { } + | DOTEQU { } + | DOTGE { } + | DOTGEU { } + | DOTGT { } + | DOTGTU { } + | DOTLE { } + | DOTLEU { } + | DOTLT { } + | DOTLTU { } + | DOTNE { } + | DOTNEU { } + | DOTNSF { } + | DOTSF { } + | DOTCARRY { } + ; + +%% + +/*support c++ functions go here*/ + |
