#!/usr/bin/env python
# -*- python -*-
#BEGIN_LEGAL
#
#Copyright (c) 2019 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


from __future__ import print_function
import re
import genutil
import codegen


def _emit_function(fe, isa_sets, name):
    fo = codegen.function_object_t('xed_classify_{}'.format(name)) 
    fo.add_arg('const xed_decoded_inst_t* d')
    fo.add_code_eol('    const xed_isa_set_enum_t isa_set = xed_decoded_inst_get_isa_set(d)')
    # FIXME: 2017-07-14 optimization: could use a static array for faster checking, smaller code
    switch = codegen.c_switch_generator_t('isa_set', fo)
    isa_sets_sorted = sorted(isa_sets)
    for c in isa_sets_sorted:
        switch.add_case('XED_ISA_SET_{}'.format(c.upper()),[],do_break=False)
    if len(isa_sets) > 0:
        switch.add('return 1;')
    switch.add_default(['return 0;'], do_break=False)
    switch.finish()
    
    fo.emit_file_emitter(fe)


def work(agi):
    sse_isa_sets = set([])
    avx_isa_sets = set([])
    avx512_isa_sets = set([])
    avx512_kmask_op = set([])
    for generator in agi.generator_list:
      for ii in generator.parser_output.instructions:
         if genutil.field_check(ii, 'iclass'):
             if re.search('AVX512',ii.isa_set):
                 avx512_isa_sets.add(ii.isa_set)
                 if re.search('KOP',ii.isa_set):
                     avx512_kmask_op.add(ii.isa_set)
             elif re.search('AVX',ii.isa_set) or ii.isa_set in ['F16C', 'FMA']:
                 avx_isa_sets.add(ii.isa_set)
             elif re.search('SSE',ii.isa_set) or ii.isa_set in ['AES','PCLMULQDQ']:
                 # Exclude MMX instructions that come in with SSE2 &
                 # SSSE3. The several purely MMX instr in SSE are
                 # "SSE-opcodes" with memop operands. One can look for
                 # those with SSE2MMX and SSSE3MMX xed isa_sets.
                 #
                 # Also exclude the SSE_PREFETCH operations; Those are
                 # just memops.
                 if (not re.search('MMX',ii.isa_set) and not re.search('PREFETCH',ii.isa_set)
                     and not re.search('X87',ii.isa_set) and not re.search('MWAIT',ii.isa_set)):
                     sse_isa_sets.add(ii.isa_set)
                 
    fe = agi.open_file('xed-classifiers.c') # xed_file_emitter_t
    _emit_function(fe, avx512_isa_sets, 'avx512')
    _emit_function(fe, avx512_kmask_op, 'avx512_maskop')
    _emit_function(fe, avx_isa_sets,    'avx')
    _emit_function(fe, sse_isa_sets,    'sse')
    fe.close()
    return

[((33, 13, 33, 56), 'codegen.c_switch_generator_t', 'codegen.c_switch_generator_t', ({(33, 42, 33, 51): '"""isa_set"""', (33, 53, 33, 55): 'fo'}, {}), "('isa_set', fo)", False, 'import codegen\n'), ((52, 12, 52, 45), 'genutil.field_check', 'genutil.field_check', ({(52, 32, 52, 34): 'ii', (52, 36, 52, 44): '"""iclass"""'}, {}), "(ii, 'iclass')", False, 'import genutil\n'), ((53, 16, 53, 46), 're.search', 're.search', ({(53, 26, 53, 34): '"""AVX512"""', (53, 35, 53, 45): 'ii.isa_set'}, {}), "('AVX512', ii.isa_set)", False, 'import re\n'), ((55, 20, 55, 47), 're.search', 're.search', ({(55, 30, 55, 35): '"""KOP"""', (55, 36, 55, 46): 'ii.isa_set'}, {}), "('KOP', ii.isa_set)", False, 'import re\n'), ((57, 18, 57, 45), 're.search', 're.search', ({(57, 28, 57, 33): '"""AVX"""', (57, 34, 57, 44): 'ii.isa_set'}, {}), "('AVX', ii.isa_set)", False, 'import re\n'), ((59, 18, 59, 45), 're.search', 're.search', ({(59, 28, 59, 33): '"""SSE"""', (59, 34, 59, 44): 'ii.isa_set'}, {}), "('SSE', ii.isa_set)", False, 'import re\n'), ((67, 25, 67, 52), 're.search', 're.search', ({(67, 35, 67, 40): '"""MMX"""', (67, 41, 67, 51): 'ii.isa_set'}, {}), "('MMX', ii.isa_set)", False, 'import re\n'), ((67, 61, 67, 93), 're.search', 're.search', ({(67, 71, 67, 81): '"""PREFETCH"""', (67, 82, 67, 92): 'ii.isa_set'}, {}), "('PREFETCH', ii.isa_set)", False, 'import re\n'), ((68, 29, 68, 56), 're.search', 're.search', ({(68, 39, 68, 44): '"""X87"""', (68, 45, 68, 55): 'ii.isa_set'}, {}), "('X87', ii.isa_set)", False, 'import re\n'), ((68, 65, 68, 94), 're.search', 're.search', ({(68, 75, 68, 82): '"""MWAIT"""', (68, 83, 68, 93): 'ii.isa_set'}, {}), "('MWAIT', ii.isa_set)", False, 'import re\n')]