import sys import os import re import copy import struct #TODO : add parsing checks, handle errors more gracefully def toFloat24(f): f=bytearray(struct.pack('f', f)) s=f[3]>>7 tmp=(((f[3]<<1)|(f[2]>>7))&0xFF)-0x40 tmp2=(((f[0])|(f[1]<<8)|(f[2]<<16))>>7)&0xFFFF if tmp>=0: tmp2|=tmp<<16 tmp2|=s<<23 else: tmp2=s<<23 return tmp2 vshMain=None vshEndmain=None gshMain=None gshEndmain=None class DVLE(object): def __init__(self, type): self._main = 0 self._endmain = 0 self._type = type self._const = [] self._label = [] self._labelmap = {} self._outmap = [] self._inmap = [] self._symbol = bytearray() self._symbolnum = 0 def setMain(self, main): self._main = main def setEndmain(self, endmain): self._endmain = endmain #binary word tuple def addConstant(self, const): self._const.append(const) #(reg, v) def addConstantB(self, const): self._const.append(((const[0]<<16)|(0x0), const[1], 0, 0, 0)) #(reg, x, y, z, w) def addConstantI(self, const): self._const.append(((const[0]<<16)|(0x1), ((const[1]&0xff)|((const[2]&0xff)<<8)|((const[3]&0xff)<<16)|(const[4]<<24)), (0), (0), (0))) #(reg, x, y, z, w) def addConstantF(self, const): self._const.append(((const[0]<<16)|(0x2), toFloat24(const[1]), toFloat24(const[2]), toFloat24(const[3]), toFloat24(const[4]))) #string def addSymbol(self, s): ret=len(self._symbol) self._symbol+=bytearray(s, "ascii")+bytearray(b"\x00") self._symbolnum+=1 return ret #(code offset, symbol offset) def addLabel(self, label): self._label.append((label[0],self.addSymbol(label[1]))) self._labelmap[label[1]]=label[0] def getLabelAddress(self, label): if label in self._labelmap: return self._labelmap[label] else: return 0x0 #binary word tuple def addOutput(self, out): self._outmap.append(out) #(startreg, endreg, symbol offset) def addInput(self, ind): self._inmap.append((ind[0],ind[1],self.addSymbol(ind[2]))) def toBinary(self): ret=[] offsetConst=0x40 offsetLabel=offsetConst+len(self._const)*0x14 offsetOutmap=offsetLabel+len(self._label)*0x10 offsetInmap=offsetOutmap+len(self._outmap)*0x8 offsetSymbol=offsetInmap+len(self._inmap)*0x8 ret.append(0x454C5644) #DVLE magic ret.append((self._type&1)<<16) ret.append(self._main) ret.append(self._endmain) ret.append(0x00000000) # ? ret.append(0x00000000) # ? ret.append(offsetConst) ret.append(len(self._const)) ret.append(offsetLabel) ret.append(len(self._label)) ret.append(offsetOutmap) ret.append(len(self._outmap)) ret.append(offsetInmap) ret.append(len(self._inmap)) ret.append(offsetSymbol) ret.append(len(self._symbol)) for k in self._const: ret.append(k[0]) ret.append(k[1]) ret.append(k[2]) ret.append(k[3]) ret.append(k[4]) i=0 for k in self._label: ret.append(i) ret.append(k[0]) ret.append(0x00000000) # ? ret.append(k[1]) i+=1 for k in self._outmap: ret.append(k[0]) ret.append(k[1]) for k in self._inmap: ret.append(k[2]) ret.append(((k[1]&0xFFFF)<<16)|(k[0]&0xFFFF)) retb=bytearray() for k in ret: retb+=struct.pack("I",k) retb+=self._symbol return retb class DVLP(object): def __init__(self): self._code = [] self._opdesc = [] def clearCode(self): self._code[:] = [] def addInstruction(self, inst): self._code.append(inst) return len(self._code) def addOpdesc(self, opdesc): self._opdesc.append(opdesc) return len(self._opdesc) def getCodelength(self): return len(self._code) def toBinary(self): ret=[] offsetCode=0x28 offsetOpdesc=offsetCode+len(self._code)*0x4 symbolOffset=offsetOpdesc+len(self._opdesc)*0x8 ret.append(0x504C5644) #DVLP magic ret.append(0x00000000) # ? ret.append(offsetCode) ret.append(len(self._code)) ret.append(offsetOpdesc) ret.append(len(self._opdesc)) ret.append(symbolOffset) ret.append(0x00000000) # ? ret.append(0x00000000) # ? ret.append(0x00000000) # ? retb=bytearray() for k in ret: retb+=struct.pack("I",k) for k in self._code: retb+=struct.pack("I",k) for k in self._opdesc: retb+=struct.pack("I",k[0]) retb+=struct.pack("I",k[1]) return retb class DVLB(object): def __init__(self): self._dvlp = DVLP() self._dvle = [] def getDVLP(self): return self._dvlp def addDVLE(self, dvle): self._dvle.append(dvle) def toBinary(self): ret=[] ret.append(0x424C5644) #DVLB magic ret.append(len(self._dvle)) off=len(self._dvle)*0x4+0x8 retb=bytearray() retb+=self._dvlp.toBinary() for k in self._dvle: retb+=bytearray([0x00]*(0 if len(retb)%4==0 else 4-(len(retb)%4))) ret.append(off+len(retb)) retb+=k.toBinary() retb2=bytearray() for k in ret: retb2+=struct.pack("I",k) return retb2+retb def getRegisterFromNameDst(s): if s[0]=="o": # output return int(s[1:]) elif s[0]=="v": # attribute print("error : "+s+" cannot be accessed from dst") elif s[0]=="r": # temporary register return int(s[1:])+0x10 elif s[0]=="c": # uniform print("error : "+s+" cannot be accessed from dst") elif s[0]=="d": # direct hex; unambiguous return int("0x"+s[1:],0) else: print("error : "+s+" is not a valid register name") def getRegisterFromNameSrc1(s): index=0 if "[" in s: i=s.index("[") index=s[i+1:-1] s=s[:i] if index=="a0.x": index=1 elif index=="a0.y": index=2 elif index=="aL": index=3 if s[0]=="o": # output print("error : "+s+" cannot be accessed from src1") elif s[0]=="v": # attribute return (int(s[1:]), index) elif s[0]=="r": # temporary register return (int(s[1:])+0x10, index) elif s[0]=="c": # uniform return (int(s[1:])+0x20, index) elif s[0]=="d": # direct hex; unambiguous return (int("0x"+s[1:],0), index) else: print("error : "+s+" is not a valid register name") def getRegisterFromNameSrc2(s): if s[0]=="o": # output print("error : "+s+" cannot be accessed from src2") elif s[0]=="v": # attribute return int(s[1:]) elif s[0]=="r": # temporary register return int(s[1:])+0x10 elif s[0]=="c": # uniform print("error : "+s+" cannot be accessed from src2") elif s[0]=="d": # direct hex; unambiguous return int("0x"+s[1:],0) else: print("error : "+s+" is not a valid register name") def assembleFormat11(d): return (d["opcode"]<<26)|((d["dst"]&0x1F)<<24)|((d["src1"]&0x7F)<<17)|((d["src2"]&0x7F)<<10)|((d["src3"]&0x1F)<<5)|(d["extid"]&0x1F) def parseFormat11(dvle, s): operandFmt="[^\s,]*" descFmt="(?:(?:0x)[0-9a-f]+)|[0-9a-f]+" p=re.compile("^\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+")\s*\(("+descFmt+")\)") r=p.match(s) if r: src1 = getRegisterFromNameSrc1(r.group(2)) src2 = getRegisterFromNameSrc1(r.group(3)) return {"dst" : getRegisterFromNameDst(r.group(1)), "src1" : src1[0], "src2" : src2[0], "src3" : getRegisterFromNameSrc2(r.group(4)), "extid" : int(r.group(5),0)} else: raise Exception("encountered error while parsing instruction") def assembleFormat12(d): return (d["opcode"]<<26)|((d["dst"]&0x1F)<<24)|((d["src1"]&0x7F)<<17)|((d["src2"]&0x1F)<<12)|((d["src3"]&0x7F)<<5)|(d["extid"]&0x1F) def parseFormat12(dvle, s): operandFmt="[^\s,]*" descFmt="(?:(?:0x)[0-9a-f]+)|[0-9a-f]+" p=re.compile("^\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+")\s*\(("+descFmt+")\)") r=p.match(s) if r: src1 = getRegisterFromNameSrc1(r.group(2)) src3 = getRegisterFromNameSrc1(r.group(4)) return {"dst" : getRegisterFromNameDst(r.group(1)), "src1" : src1[0], "src2" : getRegisterFromNameSrc2(r.group(3)), "src3" : src3[0], "extid" : int(r.group(5),0)} else: raise Exception("encountered error while parsing instruction") def assembleFormat1(d): return (d["opcode"]<<26)|((d["dst"]&0x1F)<<21)|((d["idx"]&0x3)<<19)|((d["src1"]&0x7F)<<12)|((d["src2"]&0x1F)<<7)|(d["extid"]&0x7F) def parseFormat1(dvle, s): operandFmt="[^\s,]*" descFmt="(?:(?:0x)[0-9a-f]+)|[0-9a-f]+" p=re.compile("^\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+")\s*\(("+descFmt+")\)") r=p.match(s) if r: src1 = getRegisterFromNameSrc1(r.group(2)) return {"dst" : getRegisterFromNameDst(r.group(1)), "src1" : src1[0], "idx" : src1[1], "src2" : getRegisterFromNameSrc2(r.group(3)), "extid" : int(r.group(4),0)} else: raise Exception("encountered error while parsing instruction") def assembleFormat2(d): print(d) return (d["opcode"]<<26)|((d["flags"]&0xF)<<22)|((d["addr"]&0xFFF)<<10)|(d["ret"]&0x3FF) def parseFormat2(dvle, s): operandFmt1="[^\s,]*" # operandFmt3="0b[01]+" operandFmt3="([!]?)cmp.([xy])" operandFmt3=operandFmt3+"\s*(?:(&&|\|\|)\s*"+operandFmt3+")?" p=re.compile("^\s*("+operandFmt1+"),\s*("+operandFmt1+"),\s*"+operandFmt3+"\s*$") # p=re.compile("^\s*("+operandFmt1+"),\s*("+operandFmt1+"),\s*("+operandFmt3+")\s*") r=p.match(s) if r: neg = [0 if r.group(3)=="!" else 1, 0 if r.group(6)=="!" else 1] comp = [2 if r.group(4)=="y" else 3, None if r.group(7)==None else (2 if r.group(7)=="y" else 3)] op = r.group(5) if comp[0]!=comp[1]: flags=0 flags|=neg[0]<1: if l[0]==".": #directive if not(mode): p=re.compile("^\s*\.([^\s]*)(.*)") r=p.match(l) if r: name=r.group(1) if name in dirList: dirList[name](dvlp, dvle, r.group(2)) else: print(name+" : no such directive") else: v=parseLabel(l) if v: #label if not(mode): dvle.addLabel((dvlp.getCodelength(), v)) else: #instruction v=parseInstruction(dvle, l) if v: dvlp.addInstruction(v) if len(sys.argv)<3: print("AEMSTRO AS :") print(" aemstro_as.py ") else: dvlb=DVLB() vsh_dvle=DVLE(0x0) with open(sys.argv[1], "r") as f: for line in f: parseLine(dvlb.getDVLP(), vsh_dvle, line, False) dvlb.getDVLP().clearCode() with open(sys.argv[1], "r") as f: for line in f: parseLine(dvlb.getDVLP(), vsh_dvle, line, True) vsh_dvle.setMain(vsh_dvle.getLabelAddress(vshMain)) vsh_dvle.setEndmain(vsh_dvle.getLabelAddress(vshEndmain)) dvlb.addDVLE(vsh_dvle) if gshMain!=None and gshEndmain!=None: gsh_dvle=copy.deepcopy(vsh_dvle) gsh_dvle._type=0x1 gsh_dvle.setMain(gsh_dvle.getLabelAddress(gshMain)) gsh_dvle.setEndmain(gsh_dvle.getLabelAddress(gshEndmain)) dvlb.addDVLE(gsh_dvle) open(sys.argv[2],"wb").write(dvlb.toBinary())