libb43.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. """
  2. # b43 debugging library
  3. #
  4. # Copyright (C) 2008-2010 Michael Buesch <m@bues.ch>
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License version 3
  8. # as published by the Free Software Foundation.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. """
  18. import sys
  19. import os
  20. import re
  21. import hashlib
  22. from tempfile import *
  23. # SHM routing values
  24. B43_SHM_UCODE = 0
  25. B43_SHM_SHARED = 1
  26. B43_SHM_REGS = 2
  27. B43_SHM_IHR = 3
  28. B43_SHM_RCMTA = 4
  29. class B43Exception(Exception):
  30. pass
  31. B43_MMIO_MACCTL = 0x120
  32. B43_MMIO_PSMDEBUG = 0x154
  33. B43_MACCTL_PSM_MACEN = 0x00000001
  34. B43_MACCTL_PSM_RUN = 0x00000002
  35. B43_MACCTL_PSM_JMP0 = 0x00000004
  36. B43_MACCTL_PSM_DEBUG = 0x00002000
  37. class B43PsmDebug:
  38. """Parse the contents of the PSM-debug register"""
  39. def __init__(self, reg_content):
  40. self.raw = reg_content
  41. return
  42. def getRaw(self):
  43. """Get the raw PSM-debug register value"""
  44. return self.raw
  45. def getPc(self):
  46. """Get the microcode program counter"""
  47. return self.raw & 0xFFF
  48. class B43:
  49. """Hardware access layer. This accesses the hardware through the debugfs interface."""
  50. def __init__(self, phy=None):
  51. debugfs_path = self.__debugfs_find()
  52. # Construct the debugfs b43 path to the device
  53. b43_path = debugfs_path + "/b43/"
  54. if phy:
  55. b43_path += phy
  56. else:
  57. # Get the PHY.
  58. try:
  59. phys = os.listdir(b43_path)
  60. except OSError:
  61. print "Could not find B43's debugfs directory: %s" % b43_path
  62. raise B43Exception
  63. if not phys:
  64. print "Could not find any b43 device"
  65. raise B43Exception
  66. if len(phys) != 1:
  67. print "Found multiple b43 devices."
  68. print "You must call this tool with a phyX parameter to specify a device"
  69. raise B43Exception
  70. phy = phys[0]
  71. b43_path += phy;
  72. # Open the debugfs files
  73. try:
  74. self.f_mmio16read = file(b43_path + "/mmio16read", "r+")
  75. self.f_mmio16write = file(b43_path + "/mmio16write", "w")
  76. self.f_mmio32read = file(b43_path + "/mmio32read", "r+")
  77. self.f_mmio32write = file(b43_path + "/mmio32write", "w")
  78. self.f_shm16read = file(b43_path + "/shm16read", "r+")
  79. self.f_shm16write = file(b43_path + "/shm16write", "w")
  80. self.f_shm32read = file(b43_path + "/shm32read", "r+")
  81. self.f_shm32write = file(b43_path + "/shm32write", "w")
  82. except IOError, e:
  83. print "Could not open debugfs file %s: %s" % (e.filename, e.strerror)
  84. raise B43Exception
  85. self.b43_path = b43_path
  86. return
  87. # Get the debugfs mountpoint.
  88. def __debugfs_find(self):
  89. mtab = file("/etc/mtab").read().splitlines()
  90. regexp = re.compile(r"^[\w\-_]+\s+([\w/\-_]+)\s+debugfs")
  91. path = None
  92. for line in mtab:
  93. m = regexp.match(line)
  94. if m:
  95. path = m.group(1)
  96. break
  97. if not path:
  98. print "Could not find debugfs in /etc/mtab"
  99. raise B43Exception
  100. return path
  101. def read16(self, reg):
  102. """Do a 16bit MMIO read"""
  103. try:
  104. self.f_mmio16read.seek(0)
  105. self.f_mmio16read.write("0x%X" % reg)
  106. self.f_mmio16read.flush()
  107. self.f_mmio16read.seek(0)
  108. val = self.f_mmio16read.read()
  109. except IOError, e:
  110. print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
  111. raise B43Exception
  112. return int(val, 16)
  113. def read32(self, reg):
  114. """Do a 32bit MMIO read"""
  115. try:
  116. self.f_mmio32read.seek(0)
  117. self.f_mmio32read.write("0x%X" % reg)
  118. self.f_mmio32read.flush()
  119. self.f_mmio32read.seek(0)
  120. val = self.f_mmio32read.read()
  121. except IOError, e:
  122. print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
  123. raise B43Exception
  124. return int(val, 16)
  125. def maskSet16(self, reg, mask, set):
  126. """Do a 16bit MMIO mask-and-set operation"""
  127. try:
  128. mask &= 0xFFFF
  129. set &= 0xFFFF
  130. self.f_mmio16write.seek(0)
  131. self.f_mmio16write.write("0x%X 0x%X 0x%X" % (reg, mask, set))
  132. self.f_mmio16write.flush()
  133. except IOError, e:
  134. print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
  135. raise B43Exception
  136. return
  137. def write16(self, reg, value):
  138. """Do a 16bit MMIO write"""
  139. self.maskSet16(reg, 0, value)
  140. return
  141. def maskSet32(self, reg, mask, set):
  142. """Do a 32bit MMIO mask-and-set operation"""
  143. try:
  144. mask &= 0xFFFFFFFF
  145. set &= 0xFFFFFFFF
  146. self.f_mmio32write.seek(0)
  147. self.f_mmio32write.write("0x%X 0x%X 0x%X" % (reg, mask, set))
  148. self.f_mmio32write.flush()
  149. except IOError, e:
  150. print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
  151. raise B43Exception
  152. return
  153. def write32(self, reg, value):
  154. """Do a 32bit MMIO write"""
  155. self.maskSet32(reg, 0, value)
  156. return
  157. def shmRead16(self, routing, offset):
  158. """Do a 16bit SHM read"""
  159. try:
  160. self.f_shm16read.seek(0)
  161. self.f_shm16read.write("0x%X 0x%X" % (routing, offset))
  162. self.f_shm16read.flush()
  163. self.f_shm16read.seek(0)
  164. val = self.f_shm16read.read()
  165. except IOError, e:
  166. print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
  167. raise B43Exception
  168. return int(val, 16)
  169. def shmMaskSet16(self, routing, offset, mask, set):
  170. """Do a 16bit SHM mask-and-set operation"""
  171. try:
  172. mask &= 0xFFFF
  173. set &= 0xFFFF
  174. self.f_shm16write.seek(0)
  175. self.f_shm16write.write("0x%X 0x%X 0x%X 0x%X" % (routing, offset, mask, set))
  176. self.f_shm16write.flush()
  177. except IOError, e:
  178. print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
  179. raise B43Exception
  180. return
  181. def shmWrite16(self, routing, offset, value):
  182. """Do a 16bit SHM write"""
  183. self.shmMaskSet16(routing, offset, 0, value)
  184. return
  185. def shmRead32(self, routing, offset):
  186. """Do a 32bit SHM read"""
  187. try:
  188. self.f_shm32read.seek(0)
  189. self.f_shm32read.write("0x%X 0x%X" % (routing, offset))
  190. self.f_shm32read.flush()
  191. self.f_shm32read.seek(0)
  192. val = self.f_shm32read.read()
  193. except IOError, e:
  194. print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
  195. raise B43Exception
  196. return int(val, 16)
  197. def shmMaskSet32(self, routing, offset, mask, set):
  198. """Do a 32bit SHM mask-and-set operation"""
  199. try:
  200. mask &= 0xFFFFFFFF
  201. set &= 0xFFFFFFFF
  202. self.f_shm32write.seek(0)
  203. self.f_shm32write.write("0x%X 0x%X 0x%X 0x%X" % (routing, offset, mask, set))
  204. self.f_shm32write.flush()
  205. except IOError, e:
  206. print "Could not access debugfs file %s: %s" % (e.filename, e.strerror)
  207. raise B43Exception
  208. return
  209. def shmWrite32(self, routing, offset, value):
  210. """Do a 32bit SHM write"""
  211. self.shmMaskSet32(routing, offset, 0, value)
  212. return
  213. def getGprs(self):
  214. """Returns an array of 64 ints. One for each General Purpose register."""
  215. ret = []
  216. for i in range(0, 64):
  217. val = self.shmRead16(B43_SHM_REGS, i)
  218. ret.append(val)
  219. return ret
  220. def getLinkRegs(self):
  221. """Returns an array of 4 ints. One for each Link Register."""
  222. ret = []
  223. for i in range(0, 4):
  224. val = self.read16(0x4D0 + (i * 2))
  225. ret.append(val)
  226. return ret
  227. def getOffsetRegs(self):
  228. """Returns an array of 7 ints. One for each Offset Register."""
  229. ret = []
  230. for i in range(0, 7):
  231. val = self.read16(0x4C0 + (i * 2))
  232. ret.append(val)
  233. return ret
  234. def shmSharedRead(self):
  235. """Returns a string containing the SHM contents."""
  236. ret = ""
  237. for i in range(0, 4096, 4):
  238. val = self.shmRead32(B43_SHM_SHARED, i)
  239. ret += "%c%c%c%c" % (val & 0xFF,
  240. (val >> 8) & 0xFF,
  241. (val >> 16) & 0xFF,
  242. (val >> 24) & 0xFF)
  243. return ret
  244. def getPsmDebug(self):
  245. """Read the PSM-debug register and return an instance of B43PsmDebug."""
  246. val = self.read32(B43_MMIO_PSMDEBUG)
  247. return B43PsmDebug(val)
  248. def getPsmConditions(self):
  249. """This returns the contents of the programmable-PSM-conditions register."""
  250. return self.read16(0x4D8)
  251. def ucodeStop(self):
  252. """Unconditionally stop the microcode PSM. """
  253. self.maskSet32(B43_MMIO_MACCTL, ~B43_MACCTL_PSM_RUN, 0)
  254. return
  255. def ucodeStart(self):
  256. """Unconditionally start the microcode PSM. This will restart the
  257. microcode on the current PC. It will not jump to 0. Warning: This will
  258. unconditionally restart the PSM and ignore any driver-state!"""
  259. self.maskSet32(B43_MMIO_MACCTL, ~0, B43_MACCTL_PSM_RUN)
  260. return
  261. class Disassembler:
  262. """Disassembler for b43 firmware."""
  263. def __init__(self, binaryText, b43DasmOpts):
  264. input = NamedTemporaryFile()
  265. output = NamedTemporaryFile()
  266. input.write(binaryText)
  267. input.flush()
  268. #FIXME check b43-dasm errors
  269. os.system("b43-dasm %s %s %s" % (input.name, output.name, b43DasmOpts))
  270. self.asmText = output.read()
  271. def getAsm(self):
  272. """Returns the assembly code."""
  273. return self.asmText
  274. class Assembler:
  275. """Assembler for b43 firmware."""
  276. def __init__(self, assemblyText, b43AsmOpts):
  277. input = NamedTemporaryFile()
  278. output = NamedTemporaryFile()
  279. input.write(assemblyText)
  280. input.flush()
  281. #FIXME check b43-asm errors
  282. os.system("b43-asm %s %s %s" % (input.name, output.name, b43AsmOpts))
  283. self.binaryText = output.read()
  284. def getBinary(self):
  285. """Returns the binary code."""
  286. return self.binaryText
  287. class TextPatcher:
  288. """A textfile patcher that does not include any target context.
  289. This can be used to patch b43 firmware files."""
  290. class TextLine:
  291. def __init__(self, index, line):
  292. self.index = index
  293. self.line = line
  294. self.deleted = False
  295. def __init__(self, text, expected_md5sum):
  296. sum = hashlib.md5(text).hexdigest()
  297. if sum != expected_md5sum:
  298. print "Patcher: The text does not match the expected MD5 sum"
  299. print "Expected: " + expected_md5sum
  300. print "Calculated: " + sum
  301. raise B43Exception
  302. text = text.splitlines()
  303. self.lines = []
  304. i = 0
  305. for line in text:
  306. self.lines.append(TextPatcher.TextLine(i, line))
  307. i += 1
  308. # Add an after-last dummy. Needed for the add-before logic
  309. lastDummy = TextPatcher.TextLine(i, "")
  310. lastDummy.deleted = True
  311. self.lines.append(lastDummy)
  312. def getText(self):
  313. """This returns the current text."""
  314. textLines = []
  315. for l in self.lines:
  316. if not l.deleted:
  317. textLines.append(l.line)
  318. return "\n".join(textLines)
  319. def delLine(self, linenumber):
  320. """Delete a line of text. The linenumber corresponds to the
  321. original unmodified text."""
  322. for l in self.lines:
  323. if l.index == linenumber:
  324. l.deleted = True
  325. return
  326. print "Patcher deleteLine: Did not find the line!"
  327. raise B43Exception
  328. def addText(self, beforeLineNumber, text):
  329. """Add a text before the specified linenumber. The linenumber
  330. corresponds to the original unmodified text."""
  331. text = text.splitlines()
  332. index = 0
  333. for l in self.lines:
  334. if l.index == beforeLineNumber:
  335. break
  336. index += 1
  337. if index >= len(self.lines):
  338. print "Patcher addText: Did not find the line!"
  339. raise B43Exception
  340. for l in text:
  341. self.lines.insert(index, TextPatcher.TextLine(-1, l))
  342. index += 1
  343. class B43SymbolicSpr:
  344. """This class converts numeric SPR names into symbolic SPR names."""
  345. def __init__(self, header_file):
  346. """The passed header_file parameter is a file path to the
  347. assembly file containing the symbolic SPR definitions."""
  348. try:
  349. defs = file(header_file).readlines()
  350. except IOError, e:
  351. print "B43SymbolicSpr: Could not read %s: %s" % (e.filename, e.strerror)
  352. B43Exception
  353. # Parse the definitions
  354. self.spr_names = { }
  355. r = re.compile(r"#define\s+(\w+)\s+(spr[a-fA-F0-9]+)")
  356. for line in defs:
  357. m = r.match(line)
  358. if not m:
  359. continue # unknown line
  360. name = m.group(1)
  361. offset = m.group(2)
  362. self.spr_names[offset.lower()] = name
  363. def get(self, spr):
  364. """Get the symbolic name for an SPR. The spr parameter
  365. must be a string like "sprXXX", where XXX is a hex number."""
  366. try:
  367. spr = self.spr_names[spr.lower()]
  368. except KeyError:
  369. pass # Symbol not found. Return numeric name.
  370. return spr
  371. def getRaw(self, spr_hexnumber):
  372. """Get the symbolic name for an SPR. The spr_hexnumber
  373. parameter is the hexadecimal number for the SPR."""
  374. return self.get("spr%03X" % spr_hexnumber)
  375. class B43SymbolicShm:
  376. """This class converts numeric SHM offsets into symbolic SHM names."""
  377. def __init__(self, header_file):
  378. """The passed header_file parameter is a file path to the
  379. assembly file containing the symbolic SHM definitions."""
  380. try:
  381. defs = file(header_file).readlines()
  382. except IOError, e:
  383. print "B43SymbolicShm: Could not read %s: %s" % (e.filename, e.strerror)
  384. raise B43Exception
  385. # Parse the definitions
  386. self.shm_names = { }
  387. in_abi_section = False
  388. r = re.compile(r"#define\s+(\w+)\s+SHM\((\w+)\).*")
  389. for line in defs:
  390. if line.startswith("/* BEGIN ABI"):
  391. in_abi_section = True
  392. if line.startswith("/* END ABI"):
  393. in_abi_section = False
  394. if not in_abi_section:
  395. continue # Only parse ABI definitions
  396. m = r.match(line)
  397. if not m:
  398. continue # unknown line
  399. name = m.group(1)
  400. offset = int(m.group(2), 16)
  401. offset /= 2
  402. self.shm_names[offset] = name
  403. def get(self, shm_wordoffset):
  404. """Get the symbolic name for an SHM offset."""
  405. try:
  406. sym = self.shm_names[shm_wordoffset]
  407. except KeyError:
  408. # Symbol not found. Return numeric name.
  409. sym = "0x%03X" % shm_wordoffset
  410. return sym
  411. class B43SymbolicCondition:
  412. """This class converts numeric External Conditions into symbolic names."""
  413. def __init__(self, header_file):
  414. """The passed header_file parameter is a file path to the
  415. assembly file containing the symbolic condition definitions."""
  416. try:
  417. defs = file(header_file).readlines()
  418. except IOError, e:
  419. print "B43SymbolicCondition: Could not read %s: %s" % (e.filename, e.strerror)
  420. raise B43Exception
  421. # Parse the definitions
  422. self.cond_names = { }
  423. r = re.compile(r"#define\s+(\w+)\s+EXTCOND\(\s*(\w+),\s*(\d+)\s*\).*")
  424. for line in defs:
  425. m = r.match(line)
  426. if not m:
  427. continue # unknown line
  428. name = m.group(1)
  429. register = m.group(2)
  430. bit = int(m.group(3))
  431. if register == "CONDREG_RX":
  432. register = 0
  433. elif register == "CONDREG_TX":
  434. register = 2
  435. elif register == "CONDREG_PHY":
  436. register = 3
  437. elif register == "CONDREG_4":
  438. register = 4
  439. elif register == "CONDREG_PSM":
  440. continue # No lookup table for this one
  441. elif register == "CONDREG_RCM":
  442. register = 6
  443. elif register == "CONDREG_7":
  444. register = 7
  445. else:
  446. continue # unknown register
  447. cond_number = bit | (register << 4)
  448. self.cond_names[cond_number] = name
  449. def get(self, cond_number):
  450. """Get the symbolic name for an External Condition."""
  451. register = (cond_number >> 4) & 0x7
  452. bit = cond_number & 0xF
  453. eoi = ((cond_number & 0x80) != 0)
  454. cond_number &= ~0x80
  455. if register == 5: # PSM register
  456. return "COND_PSM(%d)" % bit
  457. try:
  458. sym = self.cond_names[cond_number]
  459. except KeyError:
  460. # Symbol not found. Return numeric name.
  461. sym = "0x%02X" % cond_number
  462. if eoi:
  463. sym = "EOI(%s)" % sym
  464. return sym
  465. class B43AsmLine:
  466. def __init__(self, text):
  467. self.text = text
  468. def getLine(self):
  469. return self.text
  470. def __repr__(self):
  471. return self.getLine()
  472. def isInstruction(self):
  473. return False
  474. class B43AsmInstruction(B43AsmLine):
  475. def __init__(self, opcode):
  476. self.setOpcode(opcode)
  477. self.clearOperands()
  478. def getOpcode(self):
  479. return self.opcode
  480. def setOpcode(self, opcode):
  481. self.opcode = opcode
  482. def clearOperands(self):
  483. self.operands = []
  484. def addOperand(self, operand):
  485. self.operands.append(operand)
  486. def getOperands(self):
  487. return self.operands
  488. def getLine(self):
  489. ret = "\t" + self.opcode
  490. if self.operands:
  491. ret += "\t"
  492. for op in self.operands:
  493. ret += op + ", "
  494. if self.operands:
  495. ret = ret[:-2]
  496. return ret
  497. def isInstruction(self):
  498. return True
  499. class B43AsmParser:
  500. """A simple B43 assembly code parser."""
  501. def __init__(self, asm_code):
  502. self.__parse_code(asm_code)
  503. def __parse_code(self, asm_code):
  504. self.codelines = []
  505. label = re.compile(r"^\s*\w+:\s*$")
  506. insn_0 = re.compile(r"^\s*([@\.\w]+)\s*$")
  507. insn_2 = re.compile(r"^\s*([@\.\w]+)\s+([@\[\],\w]+),\s*([@\[\],\w]+)\s*$")
  508. insn_3 = re.compile(r"^\s*([@\.\w]+)\s+([@\[\],\w]+),\s*([@\[\],\w]+),\s*([@\[\],\w]+)\s*$")
  509. insn_5 = re.compile(r"^\s*([@\.\w]+)\s+([@\[\],\w]+),\s*([@\[\],\w]+),\s*([@\[\],\w]+),\s*([@\[\],\w]+),\s*([@\[\],\w]+)\s*$")
  510. for line in asm_code.splitlines():
  511. m = label.match(line)
  512. if m: # Label:
  513. l = B43AsmLine(line)
  514. self.codelines.append(l)
  515. continue
  516. m = insn_0.match(line)
  517. if m: # No operands
  518. insn = B43AsmInstruction(m.group(1))
  519. self.codelines.append(insn)
  520. continue
  521. m = insn_2.match(line)
  522. if m: # Two operands
  523. insn = B43AsmInstruction(m.group(1))
  524. insn.addOperand(m.group(2))
  525. insn.addOperand(m.group(3))
  526. self.codelines.append(insn)
  527. continue
  528. m = insn_3.match(line)
  529. if m: # Three operands
  530. insn = B43AsmInstruction(m.group(1))
  531. insn.addOperand(m.group(2))
  532. insn.addOperand(m.group(3))
  533. insn.addOperand(m.group(4))
  534. self.codelines.append(insn)
  535. continue
  536. m = insn_5.match(line)
  537. if m: # Three operands
  538. insn = B43AsmInstruction(m.group(1))
  539. insn.addOperand(m.group(2))
  540. insn.addOperand(m.group(3))
  541. insn.addOperand(m.group(4))
  542. insn.addOperand(m.group(5))
  543. insn.addOperand(m.group(6))
  544. self.codelines.append(insn)
  545. continue
  546. # Unknown line
  547. l = B43AsmLine(line)
  548. self.codelines.append(l)
  549. class B43Beautifier(B43AsmParser):
  550. """A B43 assembly code beautifier."""
  551. def __init__(self, asm_code, headers_dir):
  552. """asm_code is the assembly code. headers_dir is a full
  553. path to the directory containing the symbolic SPR,SHM,etc... definitions"""
  554. if headers_dir.endswith("/"):
  555. headers_dir = headers_dir[:-1]
  556. B43AsmParser.__init__(self, asm_code)
  557. self.symSpr = B43SymbolicSpr(headers_dir + "/spr.inc")
  558. self.symShm = B43SymbolicShm(headers_dir + "/shm.inc")
  559. self.symCond = B43SymbolicCondition(headers_dir + "/cond.inc")
  560. self.preamble = "#include \"%s/spr.inc\"\n" % headers_dir
  561. self.preamble += "#include \"%s/shm.inc\"\n" % headers_dir
  562. self.preamble += "#include \"%s/cond.inc\"\n" % headers_dir
  563. self.preamble += "\n"
  564. self.__process_code()
  565. def __process_code(self):
  566. spr_re = re.compile(r"^spr\w\w\w$")
  567. shm_re = re.compile(r"^\[(0x\w+)\]$")
  568. code = self.codelines
  569. for line in code:
  570. if not line.isInstruction():
  571. continue
  572. opcode = line.getOpcode()
  573. operands = line.getOperands()
  574. # Transform unconditional jump
  575. if opcode == "jext" and int(operands[0], 16) == 0x7F:
  576. label = operands[1]
  577. line.setOpcode("jmp")
  578. line.clearOperands()
  579. line.addOperand(label)
  580. continue
  581. # Transform external conditions
  582. if opcode == "jext" or opcode == "jnext":
  583. operands[0] = self.symCond.get(int(operands[0], 16))
  584. continue
  585. # Transform orx 7,8,imm,imm,target to mov
  586. if opcode == "orx" and \
  587. int(operands[0], 16) == 7 and int(operands[1], 16) == 8 and\
  588. operands[2].startswith("0x") and operands[3].startswith("0x"):
  589. value = int(operands[3], 16) & 0xFF
  590. value |= (int(operands[2], 16) & 0xFF) << 8
  591. target = operands[4]
  592. line.setOpcode("mov")
  593. line.clearOperands()
  594. line.addOperand("0x%X" % value)
  595. line.addOperand(target)
  596. opcode = line.getOpcode()
  597. operands = line.getOperands()
  598. for i in range(0, len(operands)):
  599. o = operands[i]
  600. # Transform SPR operands
  601. m = spr_re.match(o)
  602. if m:
  603. operands[i] = self.symSpr.get(o)
  604. continue
  605. # Transform SHM operands
  606. m = shm_re.match(o)
  607. if m:
  608. offset = int(m.group(1), 16)
  609. operands[i] = "[" + self.symShm.get(offset) + "]"
  610. continue
  611. def getAsm(self):
  612. """Returns the beautified asm code."""
  613. ret = [ self.preamble ]
  614. for line in self.codelines:
  615. ret.append(str(line))
  616. return "\n".join(ret)