CompileInstruction.py 25 KB

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