about summary refs log tree commit diff stats
path: root/test/arch/mep/asm/ut_helpers_asm.py
blob: 265207871d3a0137d218012711f5070ce3b61ef7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# Toshiba MeP-c4 - unit tests helpers
# Guillaume Valadon <guillaume@valadon.net>

from __future__ import print_function

from builtins import range

from miasm2.core.utils import decode_hex, encode_hex
from miasm2.arch.mep.arch import mn_mep
from miasm2.core.cpu import Disasm_Exception
from miasm2.core.locationdb import LocationDB
from miasm2.expression.expression import ExprId, ExprInt, ExprLoc

import re


def dis(mn_hex):
    """Disassembly helper"""
    mn_bin = decode_hex(mn_hex)
    try:
        return mn_mep.dis(mn_bin, "b")
    except Disasm_Exception:
        assert(False)  # miasm don't know what to do


def check_instruction(mn_str, mn_hex, multi=None, offset=0):
    """Try to disassemble and assemble this instruction"""

    # Rename objdump registers names
    mn_str = re.sub("\$([0-9]+)", lambda m: "R"+m.group(1), mn_str)
    mn_str = mn_str.replace("$", "")

    # Disassemble
    mn = dis(mn_hex)
    mn.offset = offset
    if mn.dstflow():

        # Remember ExprInt arguments sizes
        args_size = list()
        for i in range(len(mn.args)):
            if isinstance(mn.args[i], ExprInt):
                args_size.append(mn.args[i].size)
            else:
                args_size.append(None)

        # Adjust arguments values using the instruction offset
        loc_db = LocationDB()
        mn.dstflow2label(loc_db)

        # Convert ExprLoc to ExprInt
        for i in range(len(mn.args)):
            if args_size[i] is None:
                continue
            if isinstance(mn.args[i], ExprLoc):
                addr = loc_db.get_location_offset(mn.args[i].loc_key)
                mn.args[i] = ExprInt(addr, args_size[i])

    print("dis: %s -> %s" % (mn_hex.rjust(20), str(mn).rjust(20)))
    assert(str(mn) == mn_str)  # disassemble assertion

    # Assemble and return all possible candidates
    instr = mn_mep.fromstring(mn_str, "b")
    instr.offset = offset
    instr.mode = "b"
    if instr.offset:
        instr.fixDstOffset()
    asm_list = [encode_hex(i).decode() for i in mn_mep.asm(instr)]

    # Check instructions variants
    if multi:
        print("Instructions count:", len(asm_list))
        assert(len(asm_list) == multi)

        # Ensure that variants correspond to the same disassembled instruction
        for mn_hex_tmp in asm_list:
            mn = dis(mn_hex_tmp)
            print("dis: %s -> %s" % (mn_hex_tmp.rjust(20), str(mn).rjust(20)))

    # Check the assembly result
    print(
        "asm: %s -> %s" % (
            mn_str.rjust(20),
            ", ".join(asm_list).rjust(20)
        )
    )
    assert(mn_hex in asm_list)  # assemble assertion


def launch_tests(obj):
    """Call test methods by name"""

    test_methods = [name for name in dir(obj) if name.startswith("test")]

    for method in test_methods:
        print(method)
        try:
            getattr(obj, method)()
        except AttributeError as e:
            print("Method not found: %s" % method)
            assert(False)
        print('-' * 42)