CompileInstruction.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951
  1. from bitstring import Bits
  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 CCACHE instruction
  332. #should have 0 arguments
  333. def compileCcache(line):
  334. if len(line) != 1:
  335. raise Exception("Incorrect number of arguments. Expected 0, but got " + str(len(line)-1))
  336. return "01110000000000000000000000000000 //Clear L1 Cache"
  337. #compiles ARITH/ARITHC instructions, except LOAD/LOADHI
  338. #should have 3 arguments
  339. #arg1 should be a valid register
  340. #arg2 should either be a number that is within 16 bits signed,
  341. # or a valid register
  342. #arg3 should be a valid register
  343. def compileARITH(line, opcode):
  344. if len(line) != 4:
  345. raise Exception("Incorrect number of arguments. Expected 3, but got " + str(len(line)-1))
  346. const16 = ""
  347. arg2Int = 0
  348. constantEnable = False
  349. breg = ""
  350. instruction = ""
  351. #convert arg1 to number
  352. arg1Int = getReg(line[1])
  353. #convert arg1 to binary
  354. areg = format(arg1Int, '04b')
  355. #convert arg2 to number
  356. if line[2][0].lower() == 'r': #if arg2 is a register argument
  357. constantEnable = False
  358. arg2Int = getReg(line[2])
  359. else: #arg2 is a constant
  360. constantEnable = True
  361. arg2Int= getNumber(line[2])
  362. #convert arg2 to binary
  363. if constantEnable:
  364. CheckFitsInBits(arg2Int, 16)
  365. const16 = format(arg2Int & 0xffff, '016b')
  366. else:
  367. breg = format(arg2Int, '04b')
  368. #convert arg3 to number
  369. arg3Int = getReg(line[3])
  370. #convert arg3 to binary
  371. dreg = format(arg3Int, '04b')
  372. #opcode to operation map
  373. branchOpcodeDict = {
  374. "0000" : " OR ",
  375. "0001" : " AND ",
  376. "0010" : " XOR ",
  377. "0011" : " + ",
  378. "0100" : " - ",
  379. "0101" : " << ",
  380. "0110" : " >> ",
  381. "0111" : " ~A ",
  382. "1000" : " * (signed) ",
  383. "1001" : " * (unsigned) ",
  384. "1010" : " SLT ",
  385. "1011" : " SLTU ",
  386. "1110" : " >> (signed) ",
  387. "1111" : " * (signed FP) "
  388. }
  389. #create instruction
  390. if constantEnable:
  391. instruction = "0001" + opcode + const16 + areg + dreg + " //Compute " + line[1] + branchOpcodeDict[opcode] + line[2] + " and write result to " + line[3]
  392. else:
  393. instruction = "0000" + opcode + "000000000000" + areg + breg + dreg + " //Compute " + line[1] + branchOpcodeDict[opcode] + line[2] + " and write result to " + line[3]
  394. return instruction
  395. # compiles OR instruction
  396. def compileOR(line):
  397. return compileARITH(line, "0000")
  398. # compiles AND instruction
  399. def compileAND(line):
  400. return compileARITH(line, "0001")
  401. # compiles XOR instruction
  402. def compileXOR(line):
  403. return compileARITH(line, "0010")
  404. # compiles ADD instruction
  405. def compileADD(line):
  406. return compileARITH(line, "0011")
  407. # compiles SUB instruction
  408. def compileSUB(line):
  409. return compileARITH(line, "0100")
  410. # compiles SHIFTL instruction
  411. def compileSHIFTL(line):
  412. return compileARITH(line, "0101")
  413. # compiles SHIFTR instruction
  414. def compileSHIFTR(line):
  415. return compileARITH(line, "0110")
  416. # compiles SHIFTRS instruction
  417. def compileSHIFTRS(line):
  418. return compileARITH(line, "1110")
  419. # compiles MULTS instruction
  420. def compileMULTS(line):
  421. return compileARITH(line, "1000")
  422. # compiles MULTU instruction
  423. def compileMULTU(line):
  424. return compileARITH(line, "1001")
  425. # compiles MULTFP instruction
  426. def compileMULTFP(line):
  427. return compileARITH(line, "1111")
  428. # compiles SLT instruction
  429. def compileSLT(line):
  430. return compileARITH(line, "1010")
  431. # compiles SLTU instruction
  432. def compileSLTU(line):
  433. return compileARITH(line, "1011")
  434. # compiles NOT instruction
  435. #should have 2 arguments
  436. #arg1 should be a valid register
  437. #arg2 should be a valid register
  438. def compileNOT(line):
  439. if len(line) != 3:
  440. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  441. instruction = ""
  442. #convert arg1 to number
  443. arg1Int = getReg(line[1])
  444. #convert arg2 to binary
  445. areg = format(arg1Int, '04b')
  446. #convert arg3 to number
  447. arg2Int = getReg(line[2])
  448. #convert arg3 to binary
  449. dreg = format(arg2Int, '04b')
  450. instruction = "00000111000000000000" + areg + "0000" + dreg + " //Compute NOT " + line[1] + " and write result to " + line[2]
  451. return instruction
  452. #compiles load instruction
  453. #should have 2 arguments
  454. #arg1 should be a positive number that is within 16 bits unsigned
  455. #arg2 should be a valid register
  456. def compileLoad(line):
  457. if len(line) != 3:
  458. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  459. const16 = ""
  460. #convert arg1 to number
  461. arg1Int = getNumber(line[1], False)
  462. #convert arg1 to binary
  463. CheckFitsInBits(arg1Int, 16, False)
  464. const16 = format(arg1Int, '016b')
  465. #convert arg2 to number
  466. arg2Int = getReg(line[2])
  467. #convert arg2 to binary
  468. dreg = format(arg2Int, '04b')
  469. #create instruction
  470. instruction = "00011100" + const16 + dreg + dreg + " //Set " + line[2] + " to " + line[1]
  471. return instruction
  472. #compiles loadhi instruction
  473. #should have 2 arguments
  474. #arg1 should be a positive number that is within 16 bits unsigned
  475. #arg2 should be a valid register
  476. def compileLoadHi(line):
  477. if len(line) != 3:
  478. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  479. const16 = ""
  480. #convert arg1 to number
  481. arg1Int = getNumber(line[1], False)
  482. #convert arg1 to binary
  483. CheckFitsInBits(arg1Int, 16, False)
  484. const16 = format(arg1Int, '016b')
  485. #convert arg2 to number
  486. arg2Int = getReg(line[2])
  487. #convert arg2 to binary
  488. dreg = format(arg2Int, '04b')
  489. #create instruction
  490. instruction = "00011101" + const16 + dreg + dreg + " //Set highest 16 bits of " + line[2] + " to " + line[1]
  491. return instruction
  492. #compiles addr2reg instruction
  493. #should have 2 arguments
  494. #arg 1 should be a valid label
  495. #arg 2 should be a reg
  496. def compileAddr2reg(line):
  497. if len(line) != 3:
  498. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  499. instruction = "loadLabelHigh " + line[1] + " " + line[2]
  500. #check if register is valid
  501. getReg(line[2])
  502. return instruction
  503. #compiles load32 instruction
  504. #should have 2 arguments
  505. #arg 1 should be a number within 32 bits
  506. #arg 2 should be a reg
  507. def compileLoad32(line):
  508. if len(line) != 3:
  509. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  510. const32 = ""
  511. #convert arg1 to number
  512. arg1Int, neg= getNumber(line[1], True, True)
  513. if neg:
  514. arg1Int = -arg1Int # because getNumber does ABS on it
  515. #check if it fits in 16 bits, so we can skip the loadhi
  516. if not neg:
  517. try:
  518. CheckFitsInBits(arg1Int, 16, False)
  519. return compileLoad(line)
  520. except:
  521. pass #continue
  522. #check if it fits in 32 bits
  523. if not neg:
  524. CheckFitsInBits(arg1Int, 32, False)
  525. else:
  526. if arg1Int < -2147483648:
  527. raise ValueError("Negative value " + str(arg1Int) + " does not fit in 32 bits (signed)")
  528. #convert to 32 bit
  529. const32 = ""
  530. if not neg:
  531. const32 = format(arg1Int, '032b')
  532. else:
  533. b = Bits(int=arg1Int, length=32) #signed binary notation
  534. const32 = b.bin
  535. constLow = int(const32[0:16], 2)
  536. constHigh = int(const32[16:32], 2)
  537. #create instruction
  538. instruction = "loadBoth " + str(constLow) + " " + str(constHigh) + " " + line[2]
  539. return instruction
  540. #compiles compileLoadLabelLow instruction
  541. def compileLoadLabelLow(line):
  542. if len(line) != 3:
  543. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  544. const16 = ""
  545. #convert arg1 to number
  546. arg1Int = getNumber(line[1], False)
  547. x = '{0:027b}'.format(arg1Int)
  548. #x[:11] highest 11 bits
  549. #x[11:] lowest 16 bits
  550. arg1Int = getNumber("0b" + x[11:], False)
  551. #convert arg1 to binary
  552. CheckFitsInBits(arg1Int, 16, False) #should not be needed
  553. const16 = format(arg1Int, '016b')
  554. #convert arg2 to number
  555. arg2Int = getReg(line[2])
  556. #convert arg2 to binary
  557. dreg = format(arg2Int, '04b')
  558. #create instruction
  559. instruction = "00011100" + const16 + dreg + dreg + " //Set " + line[2] + " to " + str(arg1Int)
  560. return instruction
  561. #compiles compileLoadLabelHigh instruction
  562. def compileLoadLabelHigh(line):
  563. if len(line) != 3:
  564. raise Exception("Incorrect number of arguments. Expected 2, but got " + str(len(line)-1))
  565. const16 = ""
  566. #convert arg1 to number
  567. arg1Int = getNumber(line[1], False)
  568. x = '{0:027b}'.format(arg1Int)
  569. #x[:11] highest 4 bits
  570. #x[11:] lowest 16 bits
  571. arg1Int = getNumber("0b" + x[:11], False)
  572. #convert arg1 to binary
  573. CheckFitsInBits(arg1Int, 16, False)
  574. const16 = format(arg1Int, '016b')
  575. #convert arg2 to number
  576. arg2Int = getReg(line[2])
  577. #convert arg2 to binary
  578. dreg = format(arg2Int, '04b')
  579. #create instruction
  580. instruction = "00011101" + const16 + dreg + dreg + " //Set highest 16 bits of " + line[2] + " to " + str(arg1Int)
  581. return instruction
  582. #compiles nop instruction
  583. #should have 0 arguments
  584. def compileNop(line):
  585. if len(line) != 1:
  586. raise Exception("Incorrect number of arguments. Expected 0, but got " + str(len(line)-1))
  587. return "00000000000000000000000000000000 //NOP"
  588. #compiles .dw instruction
  589. def compileDw(line):
  590. if len(line) < 2:
  591. raise Exception("Incorrect number of arguments. Expected 1 or more, but got " + str(len(line)-1))
  592. instruction = "data"
  593. for i in line:
  594. if i != ".dw":
  595. number = getNumber(i, True)
  596. if i[0] == '-' and int(i, 10) < 0:
  597. CheckFitsInBits(number, 33, True)
  598. else:
  599. CheckFitsInBits(number, 32, False)
  600. instruction = instruction + " " + format(number & 0xffffffff, '032b')
  601. return instruction
  602. #compiles .dd instruction
  603. def compileDd(line):
  604. if len(line) < 2:
  605. raise Exception("Incorrect number of arguments. Expected 1 or more, but got " + str(len(line)-1))
  606. instruction = "data"
  607. counter = 1
  608. for i in line:
  609. if i != ".dd":
  610. number = getNumber(i, False)
  611. CheckFitsInBits(number, 16, False)
  612. if counter < 1:
  613. counter = counter + 1
  614. instruction = instruction + "" + '{0:016b}'.format(number)
  615. else:
  616. instruction = instruction + " " + '{0:016b}'.format(number)
  617. counter = 0
  618. if counter == 0:
  619. instruction = instruction + "0000000000000000"
  620. return instruction
  621. #compiles .db instruction
  622. def compileDb(line):
  623. if len(line) < 2:
  624. raise Exception("Incorrect number of arguments. Expected 1 or more, but got " + str(len(line)-1))
  625. instruction = "data"
  626. counter = 3
  627. for i in line:
  628. if i != ".db":
  629. number = getNumber(i, False)
  630. CheckFitsInBits(number, 8, False)
  631. if counter < 3:
  632. counter = counter + 1
  633. instruction = instruction + "" + '{0:08b}'.format(number)
  634. else:
  635. instruction = instruction + " " + '{0:08b}'.format(number)
  636. counter = 0
  637. if counter == 0:
  638. instruction = instruction + "000000000000000000000000"
  639. if counter == 1:
  640. instruction = instruction + "0000000000000000"
  641. if counter == 2:
  642. instruction = instruction + "00000000"
  643. return instruction
  644. #compiles .ds instruction by converting it to a .db instruction
  645. def compileDs(line):
  646. if len(line) != 2:
  647. raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
  648. #.db instruction
  649. dbList = []
  650. dbList.append(".db")
  651. # check for " "
  652. if (line[1][0] == "\"" and line[1][-1] == "\""):
  653. dbList = dbList + [str(ord(char)) for char in line[1][1:-1]]
  654. #TODO convert string to ascii list using [ord(char) for char in string]
  655. else:
  656. raise Exception("Invalid string: " + line[1])
  657. return compileDb(dbList)
  658. #compiles .dl
  659. #should have 1 argument or a label
  660. #arg1 should be a positive number that is within 27 bits unsigned
  661. def compileDl(line):
  662. if len(line) != 2:
  663. raise Exception("Incorrect number of arguments. Expected 1, but got " + str(len(line)-1))
  664. instruction = ""
  665. ARG1isAlabel = False
  666. try:
  667. getNumber(line[1], False)
  668. ARG1isAlabel = False
  669. except:
  670. ARG1isAlabel = True
  671. #if no label is given
  672. if not ARG1isAlabel:
  673. #convert arg1 to number
  674. arg1Int = getNumber(line[1], False)
  675. #convert arg1 to binary
  676. CheckFitsInBits(arg1Int, 27, False)
  677. const27 = format(arg1Int, '027b')
  678. #create data (only the label address)
  679. instruction = "00000" + const27 + " //Label data " + line[1]
  680. #if a label is given, process it later
  681. else:
  682. instruction = " ".join(line)
  683. return instruction
  684. #compile nothing
  685. def compileNothing(line):
  686. return "ignore"