/*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 */

#include "xed-interface.h"
#include "xed-isa-set.h"
#include "xed-chip-features-private.h"

#include "xed-chip-modes-override.h"        
void
set_chip_modes(xed_decoded_inst_t* xedd,
               xed_chip_enum_t chip,
               xed_chip_features_t* features)
{
    xed_bool_t first_prefix = 0;
    xed_uint_t p4, lzcnt, tzcnt;

    switch(chip) {
      case XED_CHIP_INVALID:
        break;
      case XED_CHIP_I86:
      case XED_CHIP_I86FP:
      case XED_CHIP_I186:
      case XED_CHIP_I186FP:
      case XED_CHIP_I286REAL:
      case XED_CHIP_I286:
      case XED_CHIP_I2186FP:
      case XED_CHIP_I386REAL:
      case XED_CHIP_I386:
      case XED_CHIP_I386FP:
      case XED_CHIP_I486REAL:
      case XED_CHIP_I486:
        first_prefix = 1;
        break;
        
      case XED_CHIP_QUARK:
        // Quark is PENTIUM ISA but not PENTIUM implementation
        first_prefix = 1;
        break;
        
      case XED_CHIP_PENTIUM:
      case XED_CHIP_PENTIUMREAL:
        xed3_operand_set_modep5(xedd,1);
        first_prefix = 1;
        break;
      case XED_CHIP_PENTIUMMMX:
      case XED_CHIP_PENTIUMMMXREAL:
        xed3_operand_set_modep5(xedd,1);
        xed3_operand_set_modep55c(xedd,1);
        first_prefix = 1;
        break;

      default:
        break;
    }

    xed_chip_modes_override(xedd, chip, features);  //replaceable function
    
    if (first_prefix)
        xed3_operand_set_mode_first_prefix(xedd,1);

    /* set the P4-ness for ISA-set rejection */
    p4 = 1;
    if (chip != XED_CHIP_INVALID)
        if ( xed_isa_set_is_valid_for_chip(XED_ISA_SET_PAUSE, chip) == 0 )
            p4 = 0;
    xed3_operand_set_p4(xedd,p4);


    /* LZCNT / TZCNT show up on HSW. LZCNT has its own CPUID bit, TZCNT is on
     * BMI1.  */
    lzcnt = 1;
    tzcnt = 1;
    if (chip != XED_CHIP_INVALID) {
        if ( xed_isa_set_is_valid_for_chip(XED_ISA_SET_LZCNT, chip) == 0 )
            lzcnt = 0;
        if ( xed_isa_set_is_valid_for_chip(XED_ISA_SET_BMI1, chip) == 0 )
            tzcnt = 0;
    }
    if (features) {
        lzcnt = xed_test_chip_features(features, XED_ISA_SET_LZCNT);
        tzcnt = xed_test_chip_features(features, XED_ISA_SET_BMI1);
    }
    xed3_operand_set_lzcnt(xedd,lzcnt);
    xed3_operand_set_tzcnt(xedd,tzcnt);

}
