xed/pysrc/ild_info.py

176 lines
6.7 KiB
Python
Raw Normal View History

#BEGIN_LEGAL
#
#Copyright (c) 2017 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#END_LEGAL
#maps without AMD
#it's important that maps are correctly ordered
ild_maps = ['0x0', '0x0F', '0x0F38', '0x0F3A',
'MAP4', 'MAP5', 'MAP6']
#0F0F is for AMD's 3dnow 0F0F instructions
#it's important that maps are correctly ordered
ild_maps_with_amd = ild_maps + ['0x0F0F','XMAP8','XMAP9','XMAPA']
#maps to dump in C header files.
ild_dump_maps = ['0x0', '0x0F']
def get_maps(is_with_amd):
if is_with_amd:
return ild_maps_with_amd
else:
return ild_maps
#return maps that should be dumped in C header files.
#Now it seems that only 0 and 0F maps should be dumped.
def get_dump_maps():
return ild_dump_maps
#10 is enough i think
storage_priority = 10
class ild_info_t(object):
def __init__(self, insn_map=None, opcode=None, incomplete_opcode=None,
missing_bits=None, has_modrm=None, eosz_nt_seq=None,
easz_nt_seq=None,
imm_nt_seq=None, disp_nt_seq=None,ext_opcode=None,
mode=None,
priority=storage_priority):
self.insn_map = insn_map
self.opcode = opcode
#Boolean, indicates if given opcode is incomplete
#that happens when last 3 bits of the opcode are taken
#for operand register definition like in 0x40 opcodes for push(or pop)
self.incomplete_opcode = incomplete_opcode
#Integer, indicates number of bits that incomplete opcode misses.
#Usually 3, but added that for generality
self.missing_bits = missing_bits
#Integer. The value of opcode << 3 + MODRM.REG when the MODRM.REG
#is the extension of the opcode. None if opcode is not extended
self.ext_opcode = ext_opcode
self.mode = mode
#String. Indicates whether instruction has MODRM byte
#and whether it is ignored.
#XED_ILD_HASMODRM_[TRUE|FALSE|IGNORE_MOD]
self.has_modrm = has_modrm
#[string] - list of EOSZ-binding NT names in pattern
self.eosz_nt_seq = eosz_nt_seq
#[string] - list of EASZ-binding NT names in pattern
self.easz_nt_seq = easz_nt_seq
#[string] - list of IMM_WIDTH-binding NT names in pattern
self.imm_nt_seq = imm_nt_seq
self.disp_nt_seq = disp_nt_seq
#Integer. Indicates the priority of the object in conflict
#resolution with other objects wit same map-opcode pair.
#Priority 0 is the highest.
#For example storage's objects have priority 10 and objects
#obtained from grammar parsing have priority 0.
self.priority = priority
#This method is important because it defines which objects conflict
def __eq__(self, other):
return (other != None and
self.insn_map == other.insn_map and
self.opcode == other.opcode and
self.has_modrm == other.has_modrm and
self.ext_opcode == other.ext_opcode and
self.mode == other.mode and
self.eosz_nt_seq == other.eosz_nt_seq and
self.easz_nt_seq == other.easz_nt_seq and
self.imm_nt_seq == other.imm_nt_seq and
self.disp_nt_seq == other.disp_nt_seq)
#This method is not less important than __eq__
def __ne__(self, other):
return (other == None or
self.insn_map != other.insn_map or
self.opcode != other.opcode or
self.has_modrm != other.has_modrm or
self.ext_opcode != other.ext_opcode or
self.mode != other.mode or
self.eosz_nt_seq != other.eosz_nt_seq or
self.easz_nt_seq != other.easz_nt_seq or
self.imm_nt_seq != other.imm_nt_seq or
self.disp_nt_seq != other.disp_nt_seq)
#not currently used. But helps to conveniently sort
#objects for pretty printing (by map-opcode values)
def sort_key(self):
return (int(self.insn_map,16) << 8) + int(self.opcode, 16)
def __str__(self):
printed_members = []
printed_members.append('MAP\t: %s' % self.insn_map)
printed_members.append('OPCODE\t: %s' % self.opcode)
printed_members.append('EXT_OPCODE\t: %s' % self.ext_opcode)
printed_members.append('MODE\t: %s' % self.mode)
printed_members.append('INCOMPLETE_OPCODE\t: %s' %
self.incomplete_opcode)
printed_members.append('HAS_MODRM\t: %s' % self.has_modrm)
printed_members.append('EOSZ_SEQ:\t %s' % self.eosz_nt_seq)
printed_members.append('IMM_SEQ\t: %s' % self.imm_nt_seq)
printed_members.append('DISP_SEQ\t: %s' % self.disp_nt_seq)
return "{\n"+ ",\n".join(printed_members) + "\n}"
#convert pattern_t object to ild_info_t object
def ptrn_to_info(pattern, prio=storage_priority):
return ild_info_t(insn_map=pattern.insn_map, opcode=pattern.opcode,
incomplete_opcode=pattern.incomplete_opcode,
missing_bits=pattern.missing_bits,
has_modrm=pattern.has_modrm,
eosz_nt_seq=pattern.eosz_nt_seq,
easz_nt_seq=pattern.easz_nt_seq,
imm_nt_seq=pattern.imm_nt_seq,
disp_nt_seq=pattern.disp_nt_seq,
ext_opcode=pattern.ext_opcode,
mode=pattern.mode,
priority=prio)
#Get pattern_t object and set of infos , create info_t object and add it
#to the set
def add_ild_info(info_set, pattern):
info = ptrn_to_info(pattern)
info_set.add(info)
#info object has property 'priority' and min priority
#will win the conflict resolution.
#For example storage's info objects have priority=10, so that
#info objects obtained from grammar (priority=0) could override them
def get_min_prio_list(info_list):
if len(info_list) == 0:
return []
min_prio = min(info_list, key=lambda x: x.priority).priority
min_list = []
for info in info_list:
if info.priority == min_prio:
min_list.append(info)
return min_list