xed/pysrc/ild_easz.py
Mark Charney e7d734962c update legal header & date for py3 ported files
Change-Id: I166833daaa56c33eca01bdf7b9aa6e74a490ba9a
(cherry picked from commit 1212ba962dff6dfbfa0bd2469327ff447ce59058)
2017-06-12 14:41:24 -04:00

190 lines
6.5 KiB
Python
Executable File

#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
import re
import ild_nt
import mbuild
import ild_codegen
import operand_storage
import genutil
import ildutil
import ild_info
_easz_token = 'EASZ'
_easz_binding_pattern = re.compile(r'EASZ=(?P<rhs>[0-9]+)')
#FIXME: we can get default NT by looking at the spine
_easz_default_nt = 'ASZ_NONTERM'
_easz_lookup_def_str = 'XED_ILD_EASZ_LOOKUP'
_easz_defines = {
'XED_ILD_EASZ_0' : 0,
'XED_ILD_EASZ_1' : 1,
'XED_ILD_EASZ_2' : 2,
'XED_ILD_EASZ_3' : 3,
}
#set up LOOKUP define to be the biggest defined value
_easz_defines[_easz_lookup_def_str] = len(_easz_defines)
#reverted _eosz_defines
_easz_defines_reverse = dict((v,k) for k, v in _easz_defines.items())
_easz_c_fn = 'xed-ild-easz.c'
_easz_header_fn = 'xed-ild-easz.h'
def get_getter_fn(ptrn_list):
if len(ptrn_list) == 0:
l1_fn = '(%s)0' % (ildutil.ild_getter_typename)
first = ptrn_list[0]
for cur in ptrn_list[1:]:
if first.easz_nt_seq != cur.easz_nt_seq:
#conflict in easz resolution functions.. should not happen
return None
return ild_codegen.get_derived_op_getter_fn(first.easz_nt_seq, _easz_token)
def is_easz_conflict(info_list):
"""
Return True/False if info list conflicts
on EASZ resolution function (EOSZ NT sequence).
"""
first_info = info_list[0]
for cur_info in info_list[1:]:
if first_info.easz_nt_seq != cur_info.easz_nt_seq:
return True
return False
def gen_getter_fn_lookup(agi, united_lookup, easz_dict): # NOT USED
"""Compute L1(conflict resolution) functions list and easz
lookup tables dict.
@param agi: all generators info
@param united_lookup: the 2D lookup by map-opcode to info objects list.
united_lookup['0x0']['0x78'] == [ild_info1, ild_info2, ... ]
@type united_lookup:
{string(insn_map) : {string(opcode): [ild_info.ild_info_t]} }
"""
l1_lookup = {}
for insn_map in united_lookup.get_maps():
l1_lookup[insn_map] = {}
for opcode in range(0, 256):
info_list = united_lookup.get_info_list(insn_map, hex(opcode))
#get only info objects with minimum priority
info_list = ild_info.get_min_prio_list(info_list)
is_conflict = False
if len(info_list) > 1:
is_conflict = is_easz_conflict(info_list)
if is_conflict:
l1_fn = None
#if map-opcode pair is undefined the lookup function ptr is NULL
#this will happen for opcodes like 0F in 0F map - totally illegal
#opcodes, that should never be looked up in runtime.
elif len(info_list) == 0:
l1_fn = '(%s)0' % (ildutil.l1_ptr_typename)
else:
#there are no conflicts, we can use the eosz_nt_seq
#function
info = info_list[0]
l1_fn = ild_nt.get_lufn(info.easz_nt_seq, _easz_token)
l1_lookup[insn_map][hex(opcode)] = l1_fn
return l1_lookup
#returns a list of names of EASZ-binding NTs in the pattern
def get_easz_nt_seq(ptrn_wrds, easz_nts):
return ild_nt.get_nt_seq(ptrn_wrds, easz_nts,
implied_nt=_easz_default_nt)
#returns a list of all sequences of EOSZ setting NTs in patterns
#each sequence is a list of strings (NT names)
def get_all_easz_seq(united_lookup):
all_seq = set()
for info in united_lookup.get_all_infos():
#lists are unhaashable, hence we have to use tuples instead
all_seq.add(tuple(info.easz_nt_seq))
#convert back to lists, in order not to surprise user
return_list = []
for nt_tuple in all_seq:
return_list.append(list(nt_tuple))
return return_list
#Parameters: agi - all generator info object
#returns a list of names of NTs that bind EASZ operand
def get_easz_binding_nts(agi):
return ild_nt.get_setting_nts(agi, _easz_token)
def get_target_opname():
return _easz_token
def get_ntseq_header_fn():
return _easz_header_fn
#dumps the xed_ild_easz.c file that defines all lookup functions
#for EASZ resolution
#FIXME: should dump header file too
def work(agi, united_lookup, easz_nts, ild_gendir, debug):
#dump lookup tables for each NT
#just for debugging
nt_arrays = []
for nt_name in easz_nts:
array = ild_nt.gen_nt_lookup(agi, nt_name, 'EASZ')
if not array:
return
nt_arrays.append(array)
ild_nt.dump_lu_arrays(agi, nt_arrays, 'ild_easz_debug.txt',
'ild_easz_debug_header.txt')
all_easz_seq = get_all_easz_seq(united_lookup)
debug.write('EASZ SEQS: %s\n' % all_easz_seq)
nt_seq_arrays = {}
for nt_seq in all_easz_seq:
array = ild_nt.gen_nt_seq_lookup(agi, nt_seq, _easz_token)
if not array:
return
nt_seq_arrays[tuple(nt_seq)] = array
#init function calls all single init functions for the created tables
init_f = ild_nt.gen_init_function(list(nt_seq_arrays.values()),
'xed_ild_easz_init')
ild_nt.dump_lu_arrays(agi, list(nt_seq_arrays.values()), _easz_c_fn,
mbuild.join('include-private', _easz_header_fn),
init_f)
getter_fos = []
for names in list(nt_seq_arrays.keys()):
arr = nt_seq_arrays[names]
getter_fo = ild_codegen.gen_derived_operand_getter(agi, _easz_token,
arr, list(names))
getter_fos.append(getter_fo)
headers = [ildutil.ild_private_header,
_easz_header_fn,
operand_storage.get_operand_accessors_fn()]
ild_codegen.dump_flist_2_header(agi, 'xed-ild-easz-getters.h',
headers,
getter_fos)
#getter_lookup = gen_getter_fn_lookup(agi, united_lookup, nt_seq_arrays)
return nt_seq_arrays