cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

gen_printinsn.py (6348B)


      1#!/usr/bin/env python3
      2
      3##
      4##  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
      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 as published by
      8##  the Free Software Foundation; either version 2 of the License, or
      9##  (at your option) any later version.
     10##
     11##  This program is distributed in the hope that it will be useful,
     12##  but WITHOUT ANY WARRANTY; without even the implied warranty of
     13##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14##  GNU General Public License for more details.
     15##
     16##  You should have received a copy of the GNU General Public License
     17##  along with this program; if not, see <http://www.gnu.org/licenses/>.
     18##
     19
     20import sys
     21import re
     22import string
     23import hex_common
     24
     25##
     26##     Generate data for printing each instruction (format string + operands)
     27##
     28def regprinter(m):
     29    str = m.group(1)
     30    str += ":".join(["%d"]*len(m.group(2)))
     31    str += m.group(3)
     32    if ('S' in m.group(1)) and (len(m.group(2)) == 1):
     33        str += "/%s"
     34    elif ('C' in m.group(1)) and (len(m.group(2)) == 1):
     35        str += "/%s"
     36    return str
     37
     38def spacify(s):
     39    # Regular expression that matches any operator that contains '=' character:
     40    opswithequal_re = '[-+^&|!<>=]?='
     41    # Regular expression that matches any assignment operator.
     42    assignment_re = '[-+^&|]?='
     43
     44    # Out of the operators that contain the = sign, if the operator is also an
     45    # assignment, spaces will be added around it, unless it's enclosed within
     46    # parentheses, or spaces are already present.
     47
     48    equals = re.compile(opswithequal_re)
     49    assign = re.compile(assignment_re)
     50
     51    slen = len(s)
     52    paren_count = {}
     53    i = 0
     54    pc = 0
     55    while i < slen:
     56        c = s[i]
     57        if c == '(':
     58            pc += 1
     59        elif c == ')':
     60            pc -= 1
     61        paren_count[i] = pc
     62        i += 1
     63
     64    # Iterate over all operators that contain the equal sign. If any
     65    # match is also an assignment operator, add spaces around it if
     66    # the parenthesis count is 0.
     67    pos = 0
     68    out = []
     69    for m in equals.finditer(s):
     70        ms = m.start()
     71        me = m.end()
     72        # t is the string that matched opswithequal_re.
     73        t = m.string[ms:me]
     74        out += s[pos:ms]
     75        pos = me
     76        if paren_count[ms] == 0:
     77            # Check if the entire string t is an assignment.
     78            am = assign.match(t)
     79            if am and len(am.group(0)) == me-ms:
     80                # Don't add spaces if they are already there.
     81                if ms > 0 and s[ms-1] != ' ':
     82                    out.append(' ')
     83                out += t
     84                if me < slen and s[me] != ' ':
     85                    out.append(' ')
     86                continue
     87        # If this is not an assignment, just append it to the output
     88        # string.
     89        out += t
     90
     91    # Append the remaining part of the string.
     92    out += s[pos:len(s)]
     93    return ''.join(out)
     94
     95def main():
     96    hex_common.read_semantics_file(sys.argv[1])
     97    hex_common.read_attribs_file(sys.argv[2])
     98
     99    immext_casere = re.compile(r'IMMEXT\(([A-Za-z])')
    100
    101    with open(sys.argv[3], 'w') as f:
    102        for tag in hex_common.tags:
    103            if not hex_common.behdict[tag]: continue
    104            extendable_upper_imm = False
    105            extendable_lower_imm = False
    106            m = immext_casere.search(hex_common.semdict[tag])
    107            if m:
    108                if m.group(1).isupper():
    109                    extendable_upper_imm = True
    110                else:
    111                    extendable_lower_imm = True
    112            beh = hex_common.behdict[tag]
    113            beh = hex_common.regre.sub(regprinter,beh)
    114            beh = hex_common.absimmre.sub(r"#%s0x%x",beh)
    115            beh = hex_common.relimmre.sub(r"PC+%s%d",beh)
    116            beh = spacify(beh)
    117            # Print out a literal "%s" at the end, used to match empty string
    118            # so C won't complain at us
    119            if ("A_VECX" in hex_common.attribdict[tag]):
    120                macname = "DEF_VECX_PRINTINFO"
    121            else: macname = "DEF_PRINTINFO"
    122            f.write('%s(%s,"%s%%s"' % (macname,tag,beh))
    123            regs_or_imms = \
    124                hex_common.reg_or_immre.findall(hex_common.behdict[tag])
    125            ri = 0
    126            seenregs = {}
    127            for allregs,a,b,c,d,allimm,immlett,bits,immshift in regs_or_imms:
    128                if a:
    129                    #register
    130                    if b in seenregs:
    131                        regno = seenregs[b]
    132                    else:
    133                        regno = ri
    134                    if len(b) == 1:
    135                        f.write(', insn->regno[%d]' % regno)
    136                        if 'S' in a:
    137                            f.write(', sreg2str(insn->regno[%d])' % regno)
    138                        elif 'C' in a:
    139                            f.write(', creg2str(insn->regno[%d])' % regno)
    140                    elif len(b) == 2:
    141                        f.write(', insn->regno[%d] + 1, insn->regno[%d]' % \
    142                            (regno,regno))
    143                    else:
    144                        print("Put some stuff to handle quads here")
    145                    if b not in seenregs:
    146                        seenregs[b] = ri
    147                        ri += 1
    148                else:
    149                    #immediate
    150                    if (immlett.isupper()):
    151                        if extendable_upper_imm:
    152                            if immlett in 'rR':
    153                                f.write(',insn->extension_valid?"##":""')
    154                            else:
    155                                f.write(',insn->extension_valid?"#":""')
    156                        else:
    157                            f.write(',""')
    158                        ii = 1
    159                    else:
    160                        if extendable_lower_imm:
    161                            if immlett in 'rR':
    162                                f.write(',insn->extension_valid?"##":""')
    163                            else:
    164                                f.write(',insn->extension_valid?"#":""')
    165                        else:
    166                            f.write(',""')
    167                        ii = 0
    168                    f.write(', insn->immed[%d]' % ii)
    169            # append empty string so there is at least one more arg
    170            f.write(',"")\n')
    171
    172if __name__ == "__main__":
    173    main()