about summary refs log tree commit diff stats
path: root/miasm2/core/parse_asm.py
diff options
context:
space:
mode:
authorserpilliere <fabrice.desclaux@cea.fr>2015-10-28 22:22:01 +0100
committerFabrice Desclaux <fabrice.desclaux@cea.fr>2015-10-29 21:40:20 +0100
commit06fee2b133cd4e2d734d9e164de8028c26c636a8 (patch)
tree27edb6e718b5d4a0df0b00e48fb36fd30874be32 /miasm2/core/parse_asm.py
parentf849393c93fbf0289f4242bc6bc04b062487c461 (diff)
downloadmiasm-06fee2b133cd4e2d734d9e164de8028c26c636a8.tar.gz
miasm-06fee2b133cd4e2d734d9e164de8028c26c636a8.zip
Core/parse_asm: clean algo; support delayslot
Diffstat (limited to 'miasm2/core/parse_asm.py')
-rw-r--r--miasm2/core/parse_asm.py145
1 files changed, 87 insertions, 58 deletions
diff --git a/miasm2/core/parse_asm.py b/miasm2/core/parse_asm.py
index 178d0002..2f409172 100644
--- a/miasm2/core/parse_asm.py
+++ b/miasm2/core/parse_asm.py
@@ -5,6 +5,7 @@ import re
 import miasm2.expression.expression as m2_expr
 import miasm2.core.asmbloc as asmbloc
 from miasm2.core.cpu import gen_base_expr, parse_ast
+from miasm2.core.cpu import instruction
 
 declarator = {'byte': 8,
               'word': 16,
@@ -28,7 +29,13 @@ LABEL_RE = re.compile(r'\s*(\S+)\s*:')
 FORGET_LABEL_RE = re.compile(r'\s*\.LF[BE]\d\s*:')
 
 
-class DirectiveAlign(object):
+class Directive(object):
+
+    """Stand for Directive"""
+
+    pass
+
+class DirectiveAlign(Directive):
 
     """Stand for alignment representation"""
 
@@ -39,6 +46,20 @@ class DirectiveAlign(object):
         return "Alignment %s" % self.alignment
 
 
+class DirectiveSplit(Directive):
+
+    """Stand for alignment representation"""
+
+    pass
+
+
+class DirectiveDontSplit(Directive):
+
+    """Stand for alignment representation"""
+
+    pass
+
+
 def guess_next_new_label(symbol_pool):
     """Generate a new label
     @symbol_pool: the asm_symbol_pool instance"""
@@ -77,10 +98,10 @@ def replace_orphan_labels(instr, symbol_pool):
         instr.args[i] = instr.args[i].replace_expr(replace_id)
 
 
-
 STATE_NO_BLOC = 0
 STATE_IN_BLOC = 1
 
+
 def parse_txt(mnemo, attrib, txt, symbol_pool=None):
     """Parse an assembly listing. Returns a couple (blocks, symbol_pool), where
     blocks is a list of asm_bloc and symbol_pool the associated asm_symbol_pool
@@ -167,12 +188,10 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None):
                 # TODO
                 continue
             if directive == 'split':  # custom command
-                raw_data = asmbloc.asm_raw()
-                raw_data.split = True
-                lines.append(raw_data)
+                lines.append(DirectiveSplit())
                 continue
             if directive == 'dontsplit':  # custom command
-                lines.append(asmbloc.asm_raw())
+                lines.append(DirectiveDontSplit())
                 continue
             if directive == "align":
                 align_value = int(line[match_re.end():])
@@ -210,85 +229,95 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None):
     asmbloc.log_asmbloc.info("___pre asm oki___")
     # make blocks
 
-    block_num = 0
     cur_block = None
     state = STATE_NO_BLOC
     i = 0
     blocks = []
     block_to_nlink = None
     block_may_link = False
+    delayslot = 0
     while i < len(lines):
+        if delayslot:
+            if delayslot == 0:
+                state = STATE_NO_BLOC
+            else:
+                delayslot -= 1
+        line = lines[i]
         # no current block
         if state == STATE_NO_BLOC:
-            if not isinstance(lines[i], asmbloc.asm_label):
+            if isinstance(line, DirectiveDontSplit):
+                block_to_nlink = cur_block
+                i += 1
+                continue
+            elif isinstance(line, DirectiveSplit):
+                block_to_nlink = None
+                i += 1
+                continue
+            elif not isinstance(line, asmbloc.asm_label):
+                # First line must be a label. If it's not the case, generate
+                # it.
                 label = guess_next_new_label(symbol_pool)
-                lines[i:i] = [label]
+                cur_block = asmbloc.asm_bloc(label, alignment=mnemo.alignment)
             else:
-                line = lines[i]
                 cur_block = asmbloc.asm_bloc(line, alignment=mnemo.alignment)
-                cur_block.block_num = block_num
-                block_num += 1
-                blocks.append(cur_block)
-                state = STATE_IN_BLOC
                 i += 1
-                if block_to_nlink:
-                    block_to_nlink.addto(
-                        asmbloc.asm_constraint(cur_block.label,
-                                               C_NEXT))
-                    block_to_nlink = None
+            # Generate the current bloc
+            blocks.append(cur_block)
+            state = STATE_IN_BLOC
+            if block_to_nlink:
+                block_to_nlink.addto(
+                    asmbloc.asm_constraint(cur_block.label,
+                                           C_NEXT))
+            block_to_nlink = None
+            continue
 
         # in block
         elif state == STATE_IN_BLOC:
-            if isinstance(lines[i], asmbloc.asm_raw):
-                if hasattr(lines[i], 'split'):
-                    state = STATE_NO_BLOC
-                    block_may_link = False
-                    i += 1
-                else:
-                    state = STATE_IN_BLOC
-                    block_may_link = True
-                    cur_block.addline(lines[i])
-                    i += 1
-            elif isinstance(lines[i], DirectiveAlign):
-                cur_block.alignment = lines[i].alignment
-                i += 1
-            # asmbloc.asm_label
-            elif isinstance(lines[i], asmbloc.asm_label):
-                if block_may_link:
+            if isinstance(line, DirectiveSplit):
+                state = STATE_NO_BLOC
+                block_to_nlink = None
+            elif isinstance(line, DirectiveDontSplit):
+                state = STATE_NO_BLOC
+                block_to_nlink = cur_block
+            elif isinstance(line, DirectiveAlign):
+                cur_block.alignment = line.alignment
+            elif isinstance(line, asmbloc.asm_raw):
+                cur_block.addline(line)
+                block_to_nlink = cur_block
+            elif isinstance(line, asmbloc.asm_label):
+                if block_to_nlink:
                     cur_block.addto(
-                        asmbloc.asm_constraint(lines[i], C_NEXT))
-                    block_may_link = False
+                        asmbloc.asm_constraint(line, C_NEXT))
+                    block_to_nlink = None
                 state = STATE_NO_BLOC
+                continue
             # instruction
-            else:
-                cur_block.addline(lines[i])
-                if lines[i].dstflow():
-                    for dst in lines[i].getdstflow(symbol_pool):
+            elif isinstance(line, instruction):
+                cur_block.addline(line)
+                block_to_nlink = cur_block
+                if not line.breakflow():
+                    i += 1
+                    continue
+                if delayslot:
+                    raise RuntimeError("Cannot have breakflow in delayslot")
+                if line.dstflow():
+                    for dst in line.getdstflow(symbol_pool):
                         if not isinstance(dst, m2_expr.ExprId):
                             continue
                         if dst in mnemo.regs.all_regs_ids:
                             continue
                         cur_block.addto(asmbloc.asm_constraint(dst, C_TO))
 
-                    # TODO XXX redo this really
-
-                    if not lines[i].breakflow() and i + 1 < len(lines):
-                        if not isinstance(lines[i + 1], asmbloc.asm_label):
-                            label = guess_next_new_label(symbol_pool)
-                            lines[i + 1:i + 1] = [label]
-                    else:
-                        state = STATE_NO_BLOC
-
-                    if lines[i].splitflow():
-                        block_to_nlink = cur_block
-                if not lines[i].breakflow() or lines[i].splitflow():
-                    block_may_link = True
-                else:
-                    block_may_link = False
+                if not line.splitflow():
+                    block_to_nlink = None
 
-                i += 1
+                delayslot = line.delayslot
+                if delayslot == 0:
+                    state = STATE_NO_BLOC
+            else:
+                raise RuntimeError("unknown class %s" % line.__class__)
+        i += 1
 
     for block in blocks:
         asmbloc.log_asmbloc.info(block)
-
     return blocks, symbol_pool