CompileInstruction.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. from bitstring import Bits #pip install bitstring if you have not already
  2. '''
  3. Library for compiling single instructions
  4. '''
  5. #converts string to int
  6. #string can by binary, decimal or hex
  7. def getNumber(word, allowNeg=True, returnABS=False):
  8. value = 0
  9. #check for binary number
  10. if len(word) > 2 and word[:2] == '0b':
  11. try:
  12. value = int(word, 2)
  13. except ValueError:
  14. raise ValueError(str(word) + " is not a valid binary number")
  15. #check for hex number
  16. elif len(word) > 2 and word[:2] == '0x':
  17. try:
  18. value = int(word, 16)
  19. except ValueError:
  20. raise ValueError(str(word) + " is not a valid hex number")
  21. #check for decimal number
  22. else:
  23. try:
  24. value = int(word, 10)
  25. except ValueError:
  26. raise ValueError(str(word) + " is not a valid decimal number")
  27. #check for negative numbers
  28. if value < 0 and not allowNeg:
  29. raise ValueError(str(word) + " is a negative number (which are not allowed)")
  30. if allowNeg and returnABS:
  31. if value < 0:
  32. return abs(value), True
  33. else:
  34. return value, False
  35. return value
  36. #converts string to int, representing the register
  37. #string must be in format: rx
  38. #where x is a number between 0 and 15 (including 0 and 15)
  39. def getReg(word):
  40. value = 0
  41. #check if first char starts with an r
  42. if word[0].lower() == 'r':
  43. #check for rbp and rsp (rbp == r14, rsp == r15)
  44. if word.lower() == "rbp":
  45. return 14
  46. if word.lower() == "rsp":
  47. return 15
  48. #parse number after r
  49. try:
  50. value = int(word[1:], 10)
  51. except ValueError:
  52. raise ValueError("Register" + str(word) + " is not a valid register")
  53. else:
  54. raise ValueError("Register " + str(word) + " does not start with 'r'")
  55. if value < 0 or value > 15:
  56. raise ValueError("Register " + str(word) + " is not a valid register")
  57. return value
  58. #checks if the given signed value fits in the given number of bits
  59. def CheckFitsInBits(value, bits, signed=True):
  60. if signed: # signed numbers have one bit less
  61. bits -= 1
  62. if not (value.bit_length() <= bits):
  63. raise ValueError("Value " + str(value) + " does not fit in " + str(bits) + " bits")
  64. """
  65. ------------------LINE COMPILING FUNCTIONS---------------------
  66. """
  67. #compiles halt instruction
  68. #should have 0 arguments
  69. def compileHalt(line):
  70. if len(line) != 1:
  71. raise Exception("Incorrect number of arguments. Expected 0, but got " + str(len(line)-1))
  72. return "11111111111111111111111111111111 //Halt"
  73. #compiles READ instruction
  74. #should have 3 arguments
  75. #arg1 should be a signed number that fits in 16 bits
  76. #arg2 should be a valid register
  77. #arg3 should be a valid register
  78. def compileRead(line):
  79. if len(line) != 4:
  80. raise Exception("Incorrect number of arguments. Expected 3, but got " + str(len(line)-1))
  81. const16 = ""
  82. #convert arg1 to number
  83. arg1Int = getNumber(line[1])
  84. #convert arg1 to binary
  85. CheckFitsInBits(arg1Int, 16)
  86. const16 = format(arg1Int & 0xffff, '016b')
  87. #convert arg2 to number
  88. arg2Int = getReg(line[2])
  89. #convert arg2 to binary
  90. areg = format(arg2Int, '04b')
  91. #convert arg3 to number
  92. arg3Int = getReg(line[3])
  93. #convert arg3 to binary
  94. dreg = format(arg3Int, '04b')
  95. #create instruction
  96. instruction = "1110" + const16 + areg + "0000" + dreg + " //Read at address in " + line[2] + " with offset " + line[1] + " to " + line[3]
  97. return instruction
  98. #compiles WRITE instruction
  99. #should have 3 arguments
  100. #arg1 should be a signed number that fits in 16 bits
  101. #arg2 should be a valid register
  102. #arg3 should be a valid register
  103. def compileWrite(line):
  104. if len(line) != 4:
  105. raise Exception("Incorrect number of arguments. Expected 3, but got " + str(len(line)-1))
  106. const16 = ""
  107. #convert arg1 to number
  108. arg1Int = getNumber(line[1])
  109. #convert arg1 to binary
  110. CheckFitsInBits(arg1Int, 16)
  111. const16 = format(arg1Int & 0xffff, '016b')
  112. #convert arg2 to number
  113. arg2Int = getReg(line[2])
  114. #convert arg2 to binary
  115. areg = format(arg2Int, '04b')
  116. #convert arg3 to number
  117. arg3Int = getReg(line[3])
  118. #convert arg3 to binary
  119. breg = format(arg3Int, '04b')
  120. #create instruction
  121. instruction = "1101" + const16 + areg + breg + "0000" + " //Write value in " + line[3] + " to address in " + line[2] + " with offset " + line[1]
  122. return instruction
  123. #compiles INTID instruction
  124. #should have 1 argument
  125. def compileIntID(line):
  126. if len(line) != 2:
  127. raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
  128. #convert arg1 to number
  129. arg1Int = getReg(line[1])
  130. #convert arg1 to binary
  131. dreg = format(arg1Int, '04b')
  132. #create instruction
  133. instruction = "1100000000000000000000000000" + dreg + " //Save Interrupt ID to " + line[1]
  134. return instruction
  135. #compiles push instruction
  136. #should have 1 argument
  137. def compilePush(line):
  138. if len(line) != 2:
  139. raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
  140. #convert arg1 to number
  141. arg1Int = getReg(line[1])
  142. #convert arg1 to binary
  143. breg = format(arg1Int, '04b')
  144. #create instruction
  145. instruction = "101100000000000000000000" + breg + "0000" + " //Push " + line[1] + " to stack"
  146. return instruction
  147. #compiles push instruction
  148. #should have 1 argument
  149. def compilePop(line):
  150. if len(line) != 2:
  151. raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
  152. #convert arg1 to number
  153. arg1Int = getReg(line[1])
  154. #convert arg1 to binary
  155. dreg = format(arg1Int, '04b')
  156. #create instruction
  157. instruction = "1010000000000000000000000000" + dreg + " //Pop from stack to " + line[1]
  158. return instruction
  159. #compiles jump instruction
  160. #should have 1 argument or a label
  161. #arg1 should be a positive number that is within 27 bits unsigned
  162. def compileJump(line):
  163. if len(line) != 2:
  164. raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
  165. instruction = ""
  166. ARG1isAlabel = False
  167. try:
  168. getNumber(line[1], False)
  169. ARG1isAlabel = False
  170. except:
  171. ARG1isAlabel = True
  172. #if no label is given
  173. if not ARG1isAlabel:
  174. #convert arg1 to number
  175. arg1Int = getNumber(line[1], False)
  176. #convert arg1 to binary
  177. CheckFitsInBits(arg1Int, 27, False)
  178. const27 = format(arg1Int, '027b')
  179. #create instruction
  180. instruction = "1001" + const27 + "0" + " //Jump to constant address " + line[1]
  181. #if a label is given, process it later
  182. else:
  183. instruction = " ".join(line)
  184. return instruction
  185. #compiles jump instruction to offset
  186. #should have 1 argument
  187. #arg1 should be a positive number that is within 27 bits unsigned
  188. def compileJumpo(line):
  189. if len(line) != 2:
  190. raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
  191. instruction = ""
  192. #convert arg1 to number
  193. arg1Int = getNumber(line[1], False)
  194. #convert arg1 to binary
  195. CheckFitsInBits(arg1Int, 27, False)
  196. const27 = format(arg1Int, '027b')
  197. #create instruction
  198. instruction = "1001" + const27 + "1" + " //Jump to offset address " + line[1]
  199. return instruction
  200. #compiles jump instruction to reg with offset
  201. #should have 2 arguments
  202. #arg1 should be a positive number that is within 16 bits signed
  203. #arg2 should be a reg
  204. def compileJumpr(line):
  205. if len(line) != 3:
  206. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  207. instruction = ""
  208. #convert arg1 to number
  209. arg1Int= getNumber(line[1])
  210. #convert arg1 to binary
  211. CheckFitsInBits(arg1Int, 16)
  212. const16 = format(arg1Int & 0xfff, '016b')
  213. #convert arg2 to number
  214. arg2Int = getReg(line[2])
  215. #convert arg2 to binary
  216. breg = format(arg2Int, '04b')
  217. #create instruction
  218. instruction = "1000" + const16 + "0000" + breg + "000" + "0" + " //Jump to reg " + line[2] + " with offset " + line[1]
  219. return instruction
  220. #compiles jump instruction to offset in reg with offset
  221. #should have 2 arguments
  222. #arg1 should be a positive number that is within 16 bits signed
  223. #arg2 should be a reg
  224. def compileJumpro(line):
  225. if len(line) != 3:
  226. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  227. instruction = ""
  228. #convert arg1 to number
  229. arg1Int= getNumber(line[1])
  230. #convert arg1 to binary
  231. CheckFitsInBits(arg1Int, 16)
  232. const16 = format(arg1Int & 0xffff, '016b')
  233. #convert arg2 to number
  234. arg2Int = getReg(line[2])
  235. #convert arg2 to binary
  236. breg = format(arg2Int, '04b')
  237. #create instruction
  238. instruction = "1000" + const16 + "0000" + breg + "000" + "1" + " //Jump to offset in reg " + line[2] + " with offset " + line[1]
  239. return instruction
  240. #compiles branch instructions
  241. #should have 3 arguments
  242. #arg1 should be a valid register
  243. #arg2 should be a valid register
  244. #arg3 should be a positive number that is within 16 bits signed
  245. def compileBranch(line, opcode, signed):
  246. if len(line) != 4:
  247. raise Exception("Incorrect number of arguments. Expected 3, but got " + str(len(line)-1))
  248. const16 = ""
  249. #convert arg1 to number
  250. arg1Int = getReg(line[1])
  251. #convert arg1 to binary
  252. areg = format(arg1Int, '04b')
  253. #convert arg2 to number
  254. arg2Int = getReg(line[2])
  255. #convert arg2 to binary
  256. breg = format(arg2Int, '04b')
  257. arg3Int = 0
  258. #convert arg3 to number
  259. arg3Int= getNumber(line[3])
  260. #convert arg3 to binary
  261. CheckFitsInBits(arg3Int, 16)
  262. const16 = format(arg3Int & 0xffff, '016b')
  263. #signed bit
  264. signedBit = "0"
  265. signedString = "(unsigned)"
  266. if signed:
  267. signedBit = "1"
  268. signedString = "(signed)"
  269. #opcode to operation map
  270. branchOpcodeDict = {
  271. "000" : " == ",
  272. "001" : " > ",
  273. "010" : " >= ",
  274. "011" : " ?? ",
  275. "100" : " != ",
  276. "101" : " < ",
  277. "110" : " <= ",
  278. "111" : " ?? "
  279. }
  280. #create instruction
  281. instruction = "0110" + const16 + areg + breg + opcode + signedBit + " //" + signedString + " If " + line[1] + branchOpcodeDict[opcode] + line[2] + ", then jump to offset " + line[3]
  282. return instruction
  283. # compiles BEQ instruction
  284. def compileBEQ(line):
  285. return compileBranch(line, "000", False)
  286. # compiles BGT instruction
  287. def compileBGT(line):
  288. return compileBranch(line, "001", False)
  289. # compiles BGTS instruction
  290. def compileBGTS(line):
  291. return compileBranch(line, "001", True)
  292. # compiles BGE instruction
  293. def compileBGE(line):
  294. return compileBranch(line, "010", False)
  295. # compiles BGES instruction
  296. def compileBGES(line):
  297. return compileBranch(line, "010", True)
  298. # compiles BNE instruction
  299. def compileBNE(line):
  300. return compileBranch(line, "100", False)
  301. # compiles BLT instruction
  302. def compileBLT(line):
  303. return compileBranch(line, "101", False)
  304. # compiles BLTS instruction
  305. def compileBLTS(line):
  306. return compileBranch(line, "101", True)
  307. # compiles BLE instruction
  308. def compileBLE(line):
  309. return compileBranch(line, "110", False)
  310. # compiles BLES instruction
  311. def compileBLES(line):
  312. return compileBranch(line, "110", True)
  313. #compiles SAVPC instruction
  314. #should have 1 argument
  315. def compileSavPC(line):
  316. if len(line) != 2:
  317. raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
  318. #convert arg1 to number
  319. arg1Int = getReg(line[1])
  320. #convert arg1 to binary
  321. dreg = format(arg1Int, '04b')
  322. #create instruction
  323. instruction = "0101000000000000000000000000" + dreg + " //Save PC to " + line[1]
  324. return instruction
  325. #compiles RETI instruction
  326. #should have 0 arguments
  327. def compileReti(line):
  328. if len(line) != 1:
  329. raise Exception("Incorrect number of arguments. Expected 0, but got " + str(len(line)-1))
  330. return "01000000000000000000000000000000 //Return from interrupt"
  331. #compiles ARITH/ARITHC instructions, except LOAD/LOADHI
  332. #should have 3 arguments
  333. #arg1 should be a valid register
  334. #arg2 should either be a number that is within 16 bits signed,
  335. # or a valid register
  336. #arg3 should be a valid register
  337. def compileARITH(line, opcode):
  338. if len(line) != 4:
  339. raise Exception("Incorrect number of arguments. Expected 3, but got " + str(len(line)-1))
  340. const16 = ""
  341. arg2Int = 0
  342. constantEnable = False
  343. breg = ""
  344. instruction = ""
  345. #convert arg1 to number
  346. arg1Int = getReg(line[1])
  347. #convert arg1 to binary
  348. areg = format(arg1Int, '04b')
  349. #convert arg2 to number
  350. if line[2][0].lower() == 'r': #if arg2 is a register argument
  351. constantEnable = False
  352. arg2Int = getReg(line[2])
  353. else: #arg2 is a constant
  354. constantEnable = True
  355. arg2Int= getNumber(line[2])
  356. #convert arg2 to binary
  357. if constantEnable:
  358. CheckFitsInBits(arg2Int, 16)
  359. const16 = format(arg2Int & 0xffff, '016b')
  360. else:
  361. breg = format(arg2Int, '04b')
  362. #convert arg3 to number
  363. arg3Int = getReg(line[3])
  364. #convert arg3 to binary
  365. dreg = format(arg3Int, '04b')
  366. #opcode to operation map
  367. branchOpcodeDict = {
  368. "0000" : " OR ",
  369. "0001" : " AND ",
  370. "0010" : " XOR ",
  371. "0011" : " + ",
  372. "0100" : " - ",
  373. "0101" : " << ",
  374. "0110" : " >> ",
  375. "0111" : " ~A ",
  376. "1000" : " * (signed) ",
  377. "1001" : " * (unsigned) ",
  378. "1010" : " SLT ",
  379. "1011" : " SLTU "
  380. }
  381. #create instruction
  382. if constantEnable:
  383. instruction = "0001" + opcode + const16 + areg + dreg + " //Compute " + line[1] + branchOpcodeDict[opcode] + line[2] + " and write result to " + line[3]
  384. else:
  385. instruction = "0000" + opcode + "000000000000" + areg + breg + dreg + " //Compute " + line[1] + branchOpcodeDict[opcode] + line[2] + " and write result to " + line[3]
  386. return instruction
  387. # compiles OR instruction
  388. def compileOR(line):
  389. return compileARITH(line, "0000")
  390. # compiles AND instruction
  391. def compileAND(line):
  392. return compileARITH(line, "0001")
  393. # compiles XOR instruction
  394. def compileXOR(line):
  395. return compileARITH(line, "0010")
  396. # compiles ADD instruction
  397. def compileADD(line):
  398. return compileARITH(line, "0011")
  399. # compiles SUB instruction
  400. def compileSUB(line):
  401. return compileARITH(line, "0100")
  402. # compiles SHIFTL instruction
  403. def compileSHIFTL(line):
  404. return compileARITH(line, "0101")
  405. # compiles SHIFTR instruction
  406. def compileSHIFTR(line):
  407. return compileARITH(line, "0110")
  408. # compiles MULTS instruction
  409. def compileMULTS(line):
  410. return compileARITH(line, "1000")
  411. # compiles MULTU instruction
  412. def compileMULTU(line):
  413. return compileARITH(line, "1001")
  414. # compiles SLT instruction
  415. def compileSLT(line):
  416. return compileARITH(line, "1010")
  417. # compiles SLTU instruction
  418. def compileSLTU(line):
  419. return compileARITH(line, "1011")
  420. # compiles NOT instruction
  421. #should have 2 arguments
  422. #arg1 should be a valid register
  423. #arg2 should be a valid register
  424. def compileNOT(line):
  425. if len(line) != 3:
  426. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  427. instruction = ""
  428. #convert arg1 to number
  429. arg1Int = getReg(line[1])
  430. #convert arg2 to binary
  431. areg = format(arg1Int, '04b')
  432. #convert arg3 to number
  433. arg2Int = getReg(line[2])
  434. #convert arg3 to binary
  435. dreg = format(arg2Int, '04b')
  436. instruction = "00000111000000000000" + areg + "0000" + dreg + " //Compute NOT " + line[1] + " and write result to " + line[2]
  437. return instruction
  438. #compiles load instruction
  439. #should have 2 arguments
  440. #arg1 should be a positive number that is within 16 bits unsigned
  441. #arg2 should be a valid register
  442. def compileLoad(line):
  443. if len(line) != 3:
  444. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  445. const16 = ""
  446. #convert arg1 to number
  447. arg1Int = getNumber(line[1], False)
  448. #convert arg1 to binary
  449. CheckFitsInBits(arg1Int, 16, False)
  450. const16 = format(arg1Int, '016b')
  451. #convert arg2 to number
  452. arg2Int = getReg(line[2])
  453. #convert arg2 to binary
  454. dreg = format(arg2Int, '04b')
  455. #create instruction
  456. instruction = "00011100" + const16 + dreg + dreg + " //Set " + line[2] + " to " + line[1]
  457. return instruction
  458. #compiles loadhi instruction
  459. #should have 2 arguments
  460. #arg1 should be a positive number that is within 16 bits unsigned
  461. #arg2 should be a valid register
  462. def compileLoadHi(line):
  463. if len(line) != 3:
  464. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  465. const16 = ""
  466. #convert arg1 to number
  467. arg1Int = getNumber(line[1], False)
  468. #convert arg1 to binary
  469. CheckFitsInBits(arg1Int, 16, False)
  470. const16 = format(arg1Int, '016b')
  471. #convert arg2 to number
  472. arg2Int = getReg(line[2])
  473. #convert arg2 to binary
  474. dreg = format(arg2Int, '04b')
  475. #create instruction
  476. instruction = "00011101" + const16 + dreg + dreg + " //Set highest 16 bits of " + line[2] + " to " + line[1]
  477. return instruction
  478. #compiles addr2reg instruction
  479. #should have 2 arguments
  480. #arg 1 should be a valid label
  481. #arg 2 should be a reg
  482. def compileAddr2reg(line):
  483. if len(line) != 3:
  484. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  485. instruction = "loadLabelHigh " + line[1] + " " + line[2]
  486. #check if register is valid
  487. getReg(line[2])
  488. return instruction
  489. #compiles load32 instruction
  490. #should have 2 arguments
  491. #arg 1 should be a number within 32 bits
  492. #arg 2 should be a reg
  493. def compileLoad32(line):
  494. if len(line) != 3:
  495. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  496. const32 = ""
  497. #convert arg1 to number
  498. arg1Int, neg= getNumber(line[1], True, True)
  499. if neg:
  500. arg1Int = -arg1Int # because getNumber does ABS on it
  501. #check if it fits in 16 bits, so we can skip the loadhi
  502. if not neg:
  503. try:
  504. CheckFitsInBits(arg1Int, 16, False)
  505. return compileLoad(line)
  506. except:
  507. pass #continue
  508. #check if it fits in 32 bits
  509. if not neg:
  510. CheckFitsInBits(arg1Int, 32, False)
  511. else:
  512. if arg1Int < -2147483648:
  513. raise ValueError("Negative value " + str(arg1Int) + " does not fit in 32 bits (signed)")
  514. #convert to 32 bit
  515. const32 = ""
  516. if not neg:
  517. const32 = format(arg1Int, '032b')
  518. else:
  519. b = Bits(int=arg1Int, length=32) #signed binary notation
  520. const32 = b.bin
  521. constLow = int(const32[0:16], 2)
  522. constHigh = int(const32[16:32], 2)
  523. #create instruction
  524. instruction = "loadBoth " + str(constLow) + " " + str(constHigh) + " " + line[2]
  525. return instruction
  526. #compiles compileLoadLabelLow instruction
  527. def compileLoadLabelLow(line):
  528. if len(line) != 3:
  529. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  530. const16 = ""
  531. #convert arg1 to number
  532. arg1Int = getNumber(line[1], False)
  533. x = '{0:027b}'.format(arg1Int)
  534. #x[:11] highest 11 bits
  535. #x[11:] lowest 16 bits
  536. arg1Int = getNumber("0b" + x[11:], False)
  537. #convert arg1 to binary
  538. CheckFitsInBits(arg1Int, 16, False) #should not be needed
  539. const16 = format(arg1Int, '016b')
  540. #convert arg2 to number
  541. arg2Int = getReg(line[2])
  542. #convert arg2 to binary
  543. dreg = format(arg2Int, '04b')
  544. #create instruction
  545. instruction = "00011100" + const16 + dreg + dreg + " //Set " + line[2] + " to " + str(arg1Int)
  546. return instruction
  547. #compiles compileLoadLabelHigh instruction
  548. def compileLoadLabelHigh(line):
  549. if len(line) != 3:
  550. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  551. const16 = ""
  552. #convert arg1 to number
  553. arg1Int = getNumber(line[1], False)
  554. x = '{0:027b}'.format(arg1Int)
  555. #x[:11] highest 4 bits
  556. #x[11:] lowest 16 bits
  557. arg1Int = getNumber("0b" + x[:11], False)
  558. #convert arg1 to binary
  559. CheckFitsInBits(arg1Int, 16, False)
  560. const16 = format(arg1Int, '016b')
  561. #convert arg2 to number
  562. arg2Int = getReg(line[2])
  563. #convert arg2 to binary
  564. dreg = format(arg2Int, '04b')
  565. #create instruction
  566. instruction = "00011101" + const16 + dreg + dreg + " //Set highest 16 bits of " + line[2] + " to " + str(arg1Int)
  567. return instruction
  568. #compiles nop instruction
  569. #should have 0 arguments
  570. def compileNop(line):
  571. if len(line) != 1:
  572. raise Exception("Incorrect number of arguments. Expected 0, but got " + str(len(line)-1))
  573. return "00000000000000000000000000000000 //NOP"
  574. #compiles .dw instruction
  575. def compileDw(line):
  576. if len(line) < 2:
  577. raise Exception("Incorrect number of arguments. Expected 1 or more, but got " + str(len(line)-1))
  578. instruction = "data"
  579. for i in line:
  580. if i != ".dw":
  581. number = getNumber(i, False)
  582. CheckFitsInBits(number, 32, False)
  583. instruction = instruction + " " + '{0:032b}'.format(number)
  584. return instruction
  585. #compiles .dd instruction
  586. def compileDd(line):
  587. if len(line) < 2:
  588. raise Exception("Incorrect number of arguments. Expected 1 or more, but got " + str(len(line)-1))
  589. instruction = "data"
  590. counter = 1
  591. for i in line:
  592. if i != ".dd":
  593. number = getNumber(i, False)
  594. CheckFitsInBits(number, 16, False)
  595. if counter < 1:
  596. counter = counter + 1
  597. instruction = instruction + "" + '{0:016b}'.format(number)
  598. else:
  599. instruction = instruction + " " + '{0:016b}'.format(number)
  600. counter = 0
  601. if counter == 0:
  602. instruction = instruction + "0000000000000000"
  603. return instruction
  604. #compiles .db instruction
  605. def compileDb(line):
  606. if len(line) < 2:
  607. raise Exception("Incorrect number of arguments. Expected 1 or more, but got " + str(len(line)-1))
  608. instruction = "data"
  609. counter = 3
  610. for i in line:
  611. if i != ".db":
  612. number = getNumber(i, False)
  613. CheckFitsInBits(number, 8, False)
  614. if counter < 3:
  615. counter = counter + 1
  616. instruction = instruction + "" + '{0:08b}'.format(number)
  617. else:
  618. instruction = instruction + " " + '{0:08b}'.format(number)
  619. counter = 0
  620. if counter == 0:
  621. instruction = instruction + "000000000000000000000000"
  622. if counter == 1:
  623. instruction = instruction + "0000000000000000"
  624. if counter == 2:
  625. instruction = instruction + "00000000"
  626. return instruction
  627. #compiles .ds instruction by converting it to a .db instruction
  628. def compileDs(line):
  629. if len(line) != 2:
  630. raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
  631. #.db instruction
  632. dbList = []
  633. dbList.append(".db")
  634. # check for " "
  635. if (line[1][0] == "\"" and line[1][-1] == "\""):
  636. dbList = dbList + [str(ord(char)) for char in line[1][1:-1]]
  637. #TODO convert string to ascii list using [ord(char) for char in string]
  638. else:
  639. raise Exception("Invalid string: " + line[1])
  640. return compileDb(dbList)
  641. #compiles .dl
  642. #should have 1 argument or a label
  643. #arg1 should be a positive number that is within 27 bits unsigned
  644. def compileDl(line):
  645. if len(line) != 2:
  646. raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
  647. instruction = ""
  648. ARG1isAlabel = False
  649. try:
  650. getNumber(line[1], False)
  651. ARG1isAlabel = False
  652. except:
  653. ARG1isAlabel = True
  654. #if no label is given
  655. if not ARG1isAlabel:
  656. #convert arg1 to number
  657. arg1Int = getNumber(line[1], False)
  658. #convert arg1 to binary
  659. CheckFitsInBits(arg1Int, 27, False)
  660. const27 = format(arg1Int, '027b')
  661. #create data (only the label address)
  662. instruction = "00000" + const27 + " //Label data " + line[1]
  663. #if a label is given, process it later
  664. else:
  665. instruction = " ".join(line)
  666. return instruction
  667. #compile nothing
  668. def compileNothing(line):
  669. return "ignore"