xed/pysrc/ild_modrm.py
Mark Charney ffd94e705c initial commit
Change-Id: I32a6db1a17988d9df8ff69aa1672dbf08b108e8a
2016-12-16 16:09:38 -05:00

140 lines
4.4 KiB
Python
Executable File

#BEGIN_LEGAL
#
#Copyright (c) 2016 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
import ild_info
import ild_codegen
import genutil
import ildutil
_modrm_nt = 'MODRM()'
_vmodrm = 'VMODRM'
_modrm_bind = 'MOD['
_mod3_req = 'MOD=3'
_modrm_header_fn = 'xed-ild-modrm.h'
_has_modrm_true = 'XED_ILD_HASMODRM_TRUE'
_has_modrm_false = 'XED_ILD_HASMODRM_FALSE'
_has_modrm_undef = 'XED_ILD_HASMODRM_UNDEF'
#for MOV_DR and MOV_CR that ignore MODRM.MOD bits
_has_modrm_ignore = 'XED_ILD_HASMODRM_IGNORE_MOD'
_has_modrm_typename = 'xed_uint8_t'
_hasmodrm_defines = {
_has_modrm_false : 0,
_has_modrm_true : 1,
_has_modrm_ignore : 2,
_has_modrm_undef : 3,
}
#FIXME: do we want to check by NT names or do something similar to
#EOSZ/EASZ - find all NTs that bind interesting operand and look
#for them in the pattern.
#FIXME2: it seems we need to check VMODRM() NT too
def get_hasmodrm(ptrn):
"""
Return XED_ILD_HASMODRM_[TRUE|FALSE|IGNORE_MOD] string
"""
if is_ignored_mod(ptrn):
return _has_modrm_ignore
has_modrm = (_modrm_nt in ptrn) or (_modrm_bind in ptrn)
return _bool2has_modrm_str(has_modrm)
def is_ignored_mod(ptrn):
"""
Return True|False if MODRM.MOD bits are ignored
e.g. MOV_DR instruction
"""
#if MODRM.MOD is ignored then MODRM's fields should
#be bounded, but it should not be a VMODRM (SIMD
#instructions, there should not be MODRM() that uses
#MODRM's fields and there should not be a constraint MOD=3
#which is usage of MODRM.MOD too.
return (_modrm_bind in ptrn and
not _vmodrm in ptrn and
not _modrm_nt in ptrn and
not _mod3_req in ptrn)
def _resolve_modrm_conflict(info_list):
"""
Not trying to dispatch by prefixes, mode or anything else.
Because modrm doesn't have such conflicts.
"""
return None
def _is_modrm_conflict(info_list):
if len(info_list) <= 1:
return False
first = info_list[0]
for info in info_list[1:]:
if first.has_modrm != info.has_modrm:
return True
return False
def _bool2has_modrm_str(val):
"""
Returns C define string for has_modrm
"""
if val == None:
return _has_modrm_undef
if val:
return _has_modrm_true
return _has_modrm_false
def gen_modrm_lookup(united_lookup, debug):
modrm_lookup = {}
for insn_map in ild_info.get_dump_maps():
modrm_lookup[insn_map] = {}
for opcode in range(0, 256):
info_list = united_lookup.get_info_list(insn_map, hex(opcode))
info_list = ild_info.get_min_prio_list(info_list)
if len(info_list) == 0:
#no infos in map-opcode, illegal opcode
has_modrm = _has_modrm_undef
elif _is_modrm_conflict(info_list):
#conflict in has_modrm value in map-opcode's info_list
#try to resolve
info = _resolve_modrm_conflict(info_list)
if not info:
ildutil.ild_err(
'UNRESOLVED CONFLICT IN MODRM\n infos:\n%s\n' %
"\n".join([str(info) for info in info_list]))
has_modrm = info.has_modrm
else:
#several infos that agree on has_modrm property, we can choose
#any of them to get has_modrm
info = info_list[0]
has_modrm = info.has_modrm
modrm_lookup[insn_map][hex(opcode)] = has_modrm
return modrm_lookup
def work(agi, united_lookup, debug):
"""
dumps MODRM lookup tables to xed_ild_modrm.h
"""
modrm_lookup = gen_modrm_lookup(united_lookup, debug)
ild_codegen.dump_lookup(agi, modrm_lookup, 'has_modrm', _modrm_header_fn,
[], _has_modrm_typename,
define_dict=_hasmodrm_defines)