123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951 |
- from bitstring import Bits
- '''
- Library for compiling single instructions
- '''
- #converts string to int
- #string can by binary, decimal or hex
- def getNumber(word, allowNeg=True, returnABS=False):
- value = 0
- #check for binary number
- if len(word) > 2 and word[:2] == '0b':
- try:
- value = int(word, 2)
- except ValueError:
- raise ValueError(str(word) + " is not a valid binary number")
- #check for hex number
- elif len(word) > 2 and word[:2] == '0x':
- try:
- value = int(word, 16)
- except ValueError:
- raise ValueError(str(word) + " is not a valid hex number")
- #check for decimal number
- else:
- try:
- value = int(word, 10)
- except ValueError:
- raise ValueError(str(word) + " is not a valid decimal number")
- #check for negative numbers
- if value < 0 and not allowNeg:
- raise ValueError(str(word) + " is a negative number (which are not allowed)")
- if allowNeg and returnABS:
- if value < 0:
- return abs(value), True
- else:
- return value, False
- return value
- #converts string to int, representing the register
- #string must be in format: rx
- #where x is a number between 0 and 15 (including 0 and 15)
- def getReg(word):
- value = 0
-
- #check if first char starts with an r
- if word[0].lower() == 'r':
- #check for rbp and rsp (rbp == r14, rsp == r15)
- if word.lower() == "rbp":
- return 14
- if word.lower() == "rsp":
- return 15
- #parse number after r
- try:
- value = int(word[1:], 10)
- except ValueError:
- raise ValueError("Register" + str(word) + " is not a valid register")
- else:
- raise ValueError("Register " + str(word) + " does not start with 'r'")
- if value < 0 or value > 15:
- raise ValueError("Register " + str(word) + " is not a valid register")
- return value
- #checks if the given signed value fits in the given number of bits
- def CheckFitsInBits(value, bits, signed=True):
- if signed: # signed numbers have one bit less
- bits -= 1
- if not (value.bit_length() <= bits):
- raise ValueError("Value " + str(value) + " does not fit in " + str(bits) + " bits")
- """
- ------------------LINE COMPILING FUNCTIONS---------------------
- """
- #compiles halt instruction
- #should have 0 arguments
- def compileHalt(line):
- if len(line) != 1:
- raise Exception("Incorrect number of arguments. Expected 0, but got " + str(len(line)-1))
- return "11111111111111111111111111111111 //Halt"
- #compiles READ instruction
- #should have 3 arguments
- #arg1 should be a signed number that fits in 16 bits
- #arg2 should be a valid register
- #arg3 should be a valid register
- def compileRead(line):
- if len(line) != 4:
- raise Exception("Incorrect number of arguments. Expected 3, but got " + str(len(line)-1))
- const16 = ""
- #convert arg1 to number
- arg1Int = getNumber(line[1])
- #convert arg1 to binary
- CheckFitsInBits(arg1Int, 16)
- const16 = format(arg1Int & 0xffff, '016b')
- #convert arg2 to number
- arg2Int = getReg(line[2])
- #convert arg2 to binary
- areg = format(arg2Int, '04b')
- #convert arg3 to number
- arg3Int = getReg(line[3])
- #convert arg3 to binary
- dreg = format(arg3Int, '04b')
- #create instruction
- instruction = "1110" + const16 + areg + "0000" + dreg + " //Read at address in " + line[2] + " with offset " + line[1] + " to " + line[3]
- return instruction
- #compiles WRITE instruction
- #should have 3 arguments
- #arg1 should be a signed number that fits in 16 bits
- #arg2 should be a valid register
- #arg3 should be a valid register
- def compileWrite(line):
- if len(line) != 4:
- raise Exception("Incorrect number of arguments. Expected 3, but got " + str(len(line)-1))
- const16 = ""
- #convert arg1 to number
- arg1Int = getNumber(line[1])
- #convert arg1 to binary
- CheckFitsInBits(arg1Int, 16)
- const16 = format(arg1Int & 0xffff, '016b')
- #convert arg2 to number
- arg2Int = getReg(line[2])
- #convert arg2 to binary
- areg = format(arg2Int, '04b')
- #convert arg3 to number
- arg3Int = getReg(line[3])
- #convert arg3 to binary
- breg = format(arg3Int, '04b')
- #create instruction
- instruction = "1101" + const16 + areg + breg + "0000" + " //Write value in " + line[3] + " to address in " + line[2] + " with offset " + line[1]
- return instruction
- #compiles INTID instruction
- #should have 1 argument
- def compileIntID(line):
- if len(line) != 2:
- raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
- #convert arg1 to number
- arg1Int = getReg(line[1])
- #convert arg1 to binary
- dreg = format(arg1Int, '04b')
- #create instruction
- instruction = "1100000000000000000000000000" + dreg + " //Save Interrupt ID to " + line[1]
- return instruction
- #compiles push instruction
- #should have 1 argument
- def compilePush(line):
- if len(line) != 2:
- raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
- #convert arg1 to number
- arg1Int = getReg(line[1])
- #convert arg1 to binary
- breg = format(arg1Int, '04b')
- #create instruction
- instruction = "101100000000000000000000" + breg + "0000" + " //Push " + line[1] + " to stack"
- return instruction
- #compiles push instruction
- #should have 1 argument
- def compilePop(line):
- if len(line) != 2:
- raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
- #convert arg1 to number
- arg1Int = getReg(line[1])
- #convert arg1 to binary
- dreg = format(arg1Int, '04b')
- #create instruction
- instruction = "1010000000000000000000000000" + dreg + " //Pop from stack to " + line[1]
- return instruction
- #compiles jump instruction
- #should have 1 argument or a label
- #arg1 should be a positive number that is within 27 bits unsigned
- def compileJump(line):
- if len(line) != 2:
- raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
- instruction = ""
- ARG1isAlabel = False
- try:
- getNumber(line[1], False)
- ARG1isAlabel = False
- except:
- ARG1isAlabel = True
- #if no label is given
- if not ARG1isAlabel:
- #convert arg1 to number
- arg1Int = getNumber(line[1], False)
- #convert arg1 to binary
- CheckFitsInBits(arg1Int, 27, False)
- const27 = format(arg1Int, '027b')
- #create instruction
- instruction = "1001" + const27 + "0" + " //Jump to constant address " + line[1]
- #if a label is given, process it later
- else:
- instruction = " ".join(line)
- return instruction
- #compiles jump instruction to offset
- #should have 1 argument
- #arg1 should be a positive number that is within 27 bits unsigned
- def compileJumpo(line):
- if len(line) != 2:
- raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
- instruction = ""
- #convert arg1 to number
- arg1Int = getNumber(line[1], False)
- #convert arg1 to binary
- CheckFitsInBits(arg1Int, 27, False)
- const27 = format(arg1Int, '027b')
- #create instruction
- instruction = "1001" + const27 + "1" + " //Jump to offset address " + line[1]
- return instruction
- #compiles jump instruction to reg with offset
- #should have 2 arguments
- #arg1 should be a positive number that is within 16 bits signed
- #arg2 should be a reg
- def compileJumpr(line):
- if len(line) != 3:
- raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
- instruction = ""
-
- #convert arg1 to number
- arg1Int= getNumber(line[1])
- #convert arg1 to binary
- CheckFitsInBits(arg1Int, 16)
- const16 = format(arg1Int & 0xfff, '016b')
- #convert arg2 to number
- arg2Int = getReg(line[2])
- #convert arg2 to binary
- breg = format(arg2Int, '04b')
- #create instruction
- instruction = "1000" + const16 + "0000" + breg + "000" + "0" + " //Jump to reg " + line[2] + " with offset " + line[1]
- return instruction
- #compiles jump instruction to offset in reg with offset
- #should have 2 arguments
- #arg1 should be a positive number that is within 16 bits signed
- #arg2 should be a reg
- def compileJumpro(line):
- if len(line) != 3:
- raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
- instruction = ""
-
- #convert arg1 to number
- arg1Int= getNumber(line[1])
- #convert arg1 to binary
- CheckFitsInBits(arg1Int, 16)
- const16 = format(arg1Int & 0xffff, '016b')
- #convert arg2 to number
- arg2Int = getReg(line[2])
- #convert arg2 to binary
- breg = format(arg2Int, '04b')
- #create instruction
- instruction = "1000" + const16 + "0000" + breg + "000" + "1" + " //Jump to offset in reg " + line[2] + " with offset " + line[1]
- return instruction
- #compiles branch instructions
- #should have 3 arguments
- #arg1 should be a valid register
- #arg2 should be a valid register
- #arg3 should be a positive number that is within 16 bits signed
- def compileBranch(line, opcode, signed):
- if len(line) != 4:
- raise Exception("Incorrect number of arguments. Expected 3, but got " + str(len(line)-1))
- const16 = ""
- #convert arg1 to number
- arg1Int = getReg(line[1])
- #convert arg1 to binary
- areg = format(arg1Int, '04b')
- #convert arg2 to number
- arg2Int = getReg(line[2])
- #convert arg2 to binary
- breg = format(arg2Int, '04b')
- arg3Int = 0
- #convert arg3 to number
- arg3Int= getNumber(line[3])
- #convert arg3 to binary
- CheckFitsInBits(arg3Int, 16)
- const16 = format(arg3Int & 0xffff, '016b')
- #signed bit
- signedBit = "0"
- signedString = "(unsigned)"
- if signed:
- signedBit = "1"
- signedString = "(signed)"
- #opcode to operation map
- branchOpcodeDict = {
- "000" : " == ",
- "001" : " > ",
- "010" : " >= ",
- "011" : " ?? ",
- "100" : " != ",
- "101" : " < ",
- "110" : " <= ",
- "111" : " ?? "
- }
- #create instruction
- instruction = "0110" + const16 + areg + breg + opcode + signedBit + " //" + signedString + " If " + line[1] + branchOpcodeDict[opcode] + line[2] + ", then jump to offset " + line[3]
- return instruction
- # compiles BEQ instruction
- def compileBEQ(line):
- return compileBranch(line, "000", False)
- # compiles BGT instruction
- def compileBGT(line):
- return compileBranch(line, "001", False)
- # compiles BGTS instruction
- def compileBGTS(line):
- return compileBranch(line, "001", True)
- # compiles BGE instruction
- def compileBGE(line):
- return compileBranch(line, "010", False)
- # compiles BGES instruction
- def compileBGES(line):
- return compileBranch(line, "010", True)
- # compiles BNE instruction
- def compileBNE(line):
- return compileBranch(line, "100", False)
- # compiles BLT instruction
- def compileBLT(line):
- return compileBranch(line, "101", False)
- # compiles BLTS instruction
- def compileBLTS(line):
- return compileBranch(line, "101", True)
- # compiles BLE instruction
- def compileBLE(line):
- return compileBranch(line, "110", False)
- # compiles BLES instruction
- def compileBLES(line):
- return compileBranch(line, "110", True)
- #compiles SAVPC instruction
- #should have 1 argument
- def compileSavPC(line):
- if len(line) != 2:
- raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
- #convert arg1 to number
- arg1Int = getReg(line[1])
- #convert arg1 to binary
- dreg = format(arg1Int, '04b')
- #create instruction
- instruction = "0101000000000000000000000000" + dreg + " //Save PC to " + line[1]
- return instruction
- #compiles RETI instruction
- #should have 0 arguments
- def compileReti(line):
- if len(line) != 1:
- raise Exception("Incorrect number of arguments. Expected 0, but got " + str(len(line)-1))
- return "01000000000000000000000000000000 //Return from interrupt"
- #compiles CCACHE instruction
- #should have 0 arguments
- def compileCcache(line):
- if len(line) != 1:
- raise Exception("Incorrect number of arguments. Expected 0, but got " + str(len(line)-1))
- return "01110000000000000000000000000000 //Clear L1 Cache"
- #compiles ARITH/ARITHC instructions, except LOAD/LOADHI
- #should have 3 arguments
- #arg1 should be a valid register
- #arg2 should either be a number that is within 16 bits signed,
- # or a valid register
- #arg3 should be a valid register
- def compileARITH(line, opcode):
- if len(line) != 4:
- raise Exception("Incorrect number of arguments. Expected 3, but got " + str(len(line)-1))
- const16 = ""
- arg2Int = 0
- constantEnable = False
- breg = ""
- instruction = ""
- #convert arg1 to number
- arg1Int = getReg(line[1])
- #convert arg1 to binary
- areg = format(arg1Int, '04b')
- #convert arg2 to number
- if line[2][0].lower() == 'r': #if arg2 is a register argument
- constantEnable = False
- arg2Int = getReg(line[2])
- else: #arg2 is a constant
- constantEnable = True
- arg2Int= getNumber(line[2])
- #convert arg2 to binary
- if constantEnable:
- CheckFitsInBits(arg2Int, 16)
- const16 = format(arg2Int & 0xffff, '016b')
- else:
- breg = format(arg2Int, '04b')
-
- #convert arg3 to number
- arg3Int = getReg(line[3])
- #convert arg3 to binary
- dreg = format(arg3Int, '04b')
- #opcode to operation map
- branchOpcodeDict = {
- "0000" : " OR ",
- "0001" : " AND ",
- "0010" : " XOR ",
- "0011" : " + ",
- "0100" : " - ",
- "0101" : " << ",
- "0110" : " >> ",
- "0111" : " ~A ",
- "1000" : " * (signed) ",
- "1001" : " * (unsigned) ",
- "1010" : " SLT ",
- "1011" : " SLTU ",
- "1110" : " >> (signed) ",
- "1111" : " * (signed FP) "
- }
- #create instruction
- if constantEnable:
- instruction = "0001" + opcode + const16 + areg + dreg + " //Compute " + line[1] + branchOpcodeDict[opcode] + line[2] + " and write result to " + line[3]
- else:
- instruction = "0000" + opcode + "000000000000" + areg + breg + dreg + " //Compute " + line[1] + branchOpcodeDict[opcode] + line[2] + " and write result to " + line[3]
- return instruction
- # compiles OR instruction
- def compileOR(line):
- return compileARITH(line, "0000")
- # compiles AND instruction
- def compileAND(line):
- return compileARITH(line, "0001")
- # compiles XOR instruction
- def compileXOR(line):
- return compileARITH(line, "0010")
- # compiles ADD instruction
- def compileADD(line):
- return compileARITH(line, "0011")
- # compiles SUB instruction
- def compileSUB(line):
- return compileARITH(line, "0100")
- # compiles SHIFTL instruction
- def compileSHIFTL(line):
- return compileARITH(line, "0101")
- # compiles SHIFTR instruction
- def compileSHIFTR(line):
- return compileARITH(line, "0110")
- # compiles SHIFTRS instruction
- def compileSHIFTRS(line):
- return compileARITH(line, "1110")
- # compiles MULTS instruction
- def compileMULTS(line):
- return compileARITH(line, "1000")
- # compiles MULTU instruction
- def compileMULTU(line):
- return compileARITH(line, "1001")
- # compiles MULTFP instruction
- def compileMULTFP(line):
- return compileARITH(line, "1111")
- # compiles SLT instruction
- def compileSLT(line):
- return compileARITH(line, "1010")
- # compiles SLTU instruction
- def compileSLTU(line):
- return compileARITH(line, "1011")
- # compiles NOT instruction
- #should have 2 arguments
- #arg1 should be a valid register
- #arg2 should be a valid register
- def compileNOT(line):
- if len(line) != 3:
- raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
- instruction = ""
- #convert arg1 to number
- arg1Int = getReg(line[1])
- #convert arg2 to binary
- areg = format(arg1Int, '04b')
-
- #convert arg3 to number
- arg2Int = getReg(line[2])
- #convert arg3 to binary
- dreg = format(arg2Int, '04b')
- instruction = "00000111000000000000" + areg + "0000" + dreg + " //Compute NOT " + line[1] + " and write result to " + line[2]
- return instruction
- #compiles load instruction
- #should have 2 arguments
- #arg1 should be a positive number that is within 16 bits unsigned
- #arg2 should be a valid register
- def compileLoad(line):
- if len(line) != 3:
- raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
- const16 = ""
- #convert arg1 to number
- arg1Int = getNumber(line[1], False)
- #convert arg1 to binary
- CheckFitsInBits(arg1Int, 16, False)
- const16 = format(arg1Int, '016b')
- #convert arg2 to number
- arg2Int = getReg(line[2])
- #convert arg2 to binary
- dreg = format(arg2Int, '04b')
- #create instruction
- instruction = "00011100" + const16 + dreg + dreg + " //Set " + line[2] + " to " + line[1]
- return instruction
- #compiles loadhi instruction
- #should have 2 arguments
- #arg1 should be a positive number that is within 16 bits unsigned
- #arg2 should be a valid register
- def compileLoadHi(line):
- if len(line) != 3:
- raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
- const16 = ""
- #convert arg1 to number
- arg1Int = getNumber(line[1], False)
- #convert arg1 to binary
- CheckFitsInBits(arg1Int, 16, False)
- const16 = format(arg1Int, '016b')
- #convert arg2 to number
- arg2Int = getReg(line[2])
- #convert arg2 to binary
- dreg = format(arg2Int, '04b')
- #create instruction
- instruction = "00011101" + const16 + dreg + dreg + " //Set highest 16 bits of " + line[2] + " to " + line[1]
- return instruction
- #compiles addr2reg instruction
- #should have 2 arguments
- #arg 1 should be a valid label
- #arg 2 should be a reg
- def compileAddr2reg(line):
- if len(line) != 3:
- raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
- instruction = "loadLabelHigh " + line[1] + " " + line[2]
- #check if register is valid
- getReg(line[2])
- return instruction
- #compiles load32 instruction
- #should have 2 arguments
- #arg 1 should be a number within 32 bits
- #arg 2 should be a reg
- def compileLoad32(line):
- if len(line) != 3:
- raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
- const32 = ""
- #convert arg1 to number
- arg1Int, neg= getNumber(line[1], True, True)
- if neg:
- arg1Int = -arg1Int # because getNumber does ABS on it
- #check if it fits in 16 bits, so we can skip the loadhi
- if not neg:
- try:
- CheckFitsInBits(arg1Int, 16, False)
- return compileLoad(line)
- except:
- pass #continue
- #check if it fits in 32 bits
- if not neg:
- CheckFitsInBits(arg1Int, 32, False)
- else:
- if arg1Int < -2147483648:
- raise ValueError("Negative value " + str(arg1Int) + " does not fit in 32 bits (signed)")
- #convert to 32 bit
- const32 = ""
- if not neg:
- const32 = format(arg1Int, '032b')
- else:
- b = Bits(int=arg1Int, length=32) #signed binary notation
- const32 = b.bin
- constLow = int(const32[0:16], 2)
- constHigh = int(const32[16:32], 2)
- #create instruction
- instruction = "loadBoth " + str(constLow) + " " + str(constHigh) + " " + line[2]
- return instruction
- #compiles compileLoadLabelLow instruction
- def compileLoadLabelLow(line):
- if len(line) != 3:
- raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
- const16 = ""
- #convert arg1 to number
- arg1Int = getNumber(line[1], False)
- x = '{0:027b}'.format(arg1Int)
- #x[:11] highest 11 bits
- #x[11:] lowest 16 bits
- arg1Int = getNumber("0b" + x[11:], False)
- #convert arg1 to binary
- CheckFitsInBits(arg1Int, 16, False) #should not be needed
- const16 = format(arg1Int, '016b')
- #convert arg2 to number
- arg2Int = getReg(line[2])
- #convert arg2 to binary
- dreg = format(arg2Int, '04b')
- #create instruction
- instruction = "00011100" + const16 + dreg + dreg + " //Set " + line[2] + " to " + str(arg1Int)
- return instruction
- #compiles compileLoadLabelHigh instruction
- def compileLoadLabelHigh(line):
- if len(line) != 3:
- raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
- const16 = ""
- #convert arg1 to number
- arg1Int = getNumber(line[1], False)
- x = '{0:027b}'.format(arg1Int)
- #x[:11] highest 4 bits
- #x[11:] lowest 16 bits
- arg1Int = getNumber("0b" + x[:11], False)
- #convert arg1 to binary
- CheckFitsInBits(arg1Int, 16, False)
- const16 = format(arg1Int, '016b')
- #convert arg2 to number
- arg2Int = getReg(line[2])
- #convert arg2 to binary
- dreg = format(arg2Int, '04b')
- #create instruction
- instruction = "00011101" + const16 + dreg + dreg + " //Set highest 16 bits of " + line[2] + " to " + str(arg1Int)
- return instruction
- #compiles nop instruction
- #should have 0 arguments
- def compileNop(line):
- if len(line) != 1:
- raise Exception("Incorrect number of arguments. Expected 0, but got " + str(len(line)-1))
- return "00000000000000000000000000000000 //NOP"
- #compiles .dw instruction
- def compileDw(line):
- if len(line) < 2:
- raise Exception("Incorrect number of arguments. Expected 1 or more, but got " + str(len(line)-1))
-
- instruction = "data"
- for i in line:
- if i != ".dw":
- number = getNumber(i, True)
- if i[0] == '-' and int(i, 10) < 0:
- CheckFitsInBits(number, 33, True)
- else:
- CheckFitsInBits(number, 32, False)
- instruction = instruction + " " + format(number & 0xffffffff, '032b')
- return instruction
- #compiles .dd instruction
- def compileDd(line):
- if len(line) < 2:
- raise Exception("Incorrect number of arguments. Expected 1 or more, but got " + str(len(line)-1))
-
- instruction = "data"
- counter = 1
- for i in line:
- if i != ".dd":
- number = getNumber(i, False)
- CheckFitsInBits(number, 16, False)
- if counter < 1:
- counter = counter + 1
- instruction = instruction + "" + '{0:016b}'.format(number)
- else:
- instruction = instruction + " " + '{0:016b}'.format(number)
- counter = 0
- if counter == 0:
- instruction = instruction + "0000000000000000"
- return instruction
- #compiles .db instruction
- def compileDb(line):
- if len(line) < 2:
- raise Exception("Incorrect number of arguments. Expected 1 or more, but got " + str(len(line)-1))
-
- instruction = "data"
- counter = 3
- for i in line:
- if i != ".db":
- number = getNumber(i, False)
- CheckFitsInBits(number, 8, False)
- if counter < 3:
- counter = counter + 1
- instruction = instruction + "" + '{0:08b}'.format(number)
- else:
- instruction = instruction + " " + '{0:08b}'.format(number)
- counter = 0
- if counter == 0:
- instruction = instruction + "000000000000000000000000"
- if counter == 1:
- instruction = instruction + "0000000000000000"
- if counter == 2:
- instruction = instruction + "00000000"
- return instruction
- #compiles .ds instruction by converting it to a .db instruction
- def compileDs(line):
- if len(line) != 2:
- raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
- #.db instruction
- dbList = []
- dbList.append(".db")
- # check for " "
- if (line[1][0] == "\"" and line[1][-1] == "\""):
- dbList = dbList + [str(ord(char)) for char in line[1][1:-1]]
- #TODO convert string to ascii list using [ord(char) for char in string]
- else:
- raise Exception("Invalid string: " + line[1])
-
- return compileDb(dbList)
- #compiles .dl
- #should have 1 argument or a label
- #arg1 should be a positive number that is within 27 bits unsigned
- def compileDl(line):
- if len(line) != 2:
- raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
- instruction = ""
- ARG1isAlabel = False
- try:
- getNumber(line[1], False)
- ARG1isAlabel = False
- except:
- ARG1isAlabel = True
- #if no label is given
- if not ARG1isAlabel:
- #convert arg1 to number
- arg1Int = getNumber(line[1], False)
- #convert arg1 to binary
- CheckFitsInBits(arg1Int, 27, False)
- const27 = format(arg1Int, '027b')
- #create data (only the label address)
- instruction = "00000" + const27 + " //Label data " + line[1]
- #if a label is given, process it later
- else:
- instruction = " ".join(line)
- return instruction
- #compile nothing
- def compileNothing(line):
- return "ignore"
|