#BEGIN_LEGAL
#
#Copyright (c) 2025 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

# These bind the operand deciders that control the encoding
SEQUENCE ISA_BINDINGS
   FIXUP_EOSZ_ENC_BIND()
   FIXUP_EASZ_ENC_BIND()
   ASZ_NONTERM_BIND()  
   INSTRUCTIONS_BIND()      # not calling tree splitter! AVX instructions must set VEXVALID=1
   OSZ_NONTERM_ENC_BIND()   # OSZ must be after the instructions so that DF64 is bound (and before any prefixes obviously)
   PREFIX_ENC_BIND() 
   VEXED_REX_BIND()

# These emit the bits and bytes that make up the encoding
SEQUENCE ISA_EMIT
   PREFIX_ENC_EMIT() 
   VEXED_REX_EMIT()
   INSTRUCTIONS_EMIT()

VEXED_REX()::
VEXVALID=2 -> EVEX_ENC() 


#################################################
SEQUENCE EVEX_ENC_BIND
         # R,X,B R map(mmm) (byte 1)
         # W, vvvv, U, pp  (byte 2)
         # z, LL/RC, b   V', aaa ( byte 3)
         EVEX_62_REXR_ENC_BIND
         EVEX_REXX_ENC_BIND
         EVEX_REXB_ENC_BIND
         EVEX_REXR4_ENC_BIND
         EVEX_REXB4_MAP_ENC_BIND
         EVEX_REXW_VVVV_ENC_BIND
         EVEX_U_ENC_BIND
         EVEX_PP_ENC_BIND
         EVEX_LL_ENC_BIND
         AVX512_EVEX_BYTE3_ENC_BIND

         
SEQUENCE EVEX_ENC_EMIT
         EVEX_62_REXR_ENC_EMIT
         EVEX_REXX_ENC_EMIT
         EVEX_REXB_ENC_EMIT
         EVEX_REXR4_ENC_EMIT
         EVEX_REXB4_MAP_ENC_EMIT
         EVEX_REXW_VVVV_ENC_EMIT
         EVEX_U_ENC_EMIT
         EVEX_PP_ENC_EMIT
         EVEX_LL_ENC_EMIT
         AVX512_EVEX_BYTE3_ENC_EMIT


EVEX_62_REXR_ENC()::
mode64 REXR=1 -> 0x62 0b0
mode64 REXR=0 -> 0x62 0b1
mode32 REXR=1 -> error
mode32 REXR=0 -> 0x62 0b1

EVEX_REXX_ENC()::
mode64 REXX=1 -> 0b0
mode64 REXX=0 -> 0b1
mode32 REXX=1 -> error
mode32 REXX=0 -> 0b1

EVEX_REXB_ENC()::
mode64 REXB=1 -> 0b0
mode64 REXB=0 -> 0b1
mode32 REXB=1 -> error
mode32 REXB=0 -> 0b1

EVEX_REXR4_ENC()::
mode64 REXR4=1 -> 0b0
mode64 REXR4=0 -> 0b1
mode32 REXR4=1 -> error
mode32 REXR4=0 -> 0b1


EVEX_REXB4_MAP_ENC()::
mode32 REXB4=1 -> error

MAP=0 mode64 REXB4[e] -> e 0b000
MAP=0 mode32 REXB4=0  -> 0b0000
MAP=1 mode64 REXB4[e] -> e 0b001
MAP=1 mode32 REXB4=0  -> 0b0001
MAP=2 mode64 REXB4[e] -> e 0b010
MAP=2 mode32 REXB4=0  -> 0b0010
MAP=3 mode64 REXB4[e] -> e 0b011
MAP=3 mode32 REXB4=0  -> 0b0011


EVEX_REXW_VVVV_ENC()::
true REXW[w] VEXDEST3[u] VEXDEST210[ddd] -> w u_ddd

EVEX_U_ENC():: 
mode64 MOD!=3 REXX4=1 -> 0b0  # REXX4 for SIB memory operands w/ EGPR
mode32 MOD!=3 REXX4=1 -> error
otherwise             -> 0b1

EVEX_PP_ENC()::
VNP -> 0b00
V66 -> 0b01
VF3 -> 0b10
VF2 -> 0b11

EVEX_LL_ENC()::
VL_IGN=0 ROUNDC=0 SAE=0 VL128 -> LLRC=0
VL_IGN=0 ROUNDC=0 SAE=0 VL256 -> LLRC=1
VL_IGN=0 ROUNDC=0 SAE=0 VL512 -> LLRC=2

# Zero the LL bits if SAE/ROUNDC are legal but ignored
VL_IGN=1 ROUNDC=0 SAE=0 -> LLRC=0

# scalars (XED has scalars as VL128)
ROUNDC=0 SAE=1 VL128 -> LLRC=0 BCRC=1 # sae only, no rounding 
ROUNDC=1 SAE=1 VL128 -> LLRC=0 BCRC=1 # rounding only supported with sae
ROUNDC=2 SAE=1 VL128 -> LLRC=1 BCRC=1 # rounding only supported with sae
ROUNDC=3 SAE=1 VL128 -> LLRC=2 BCRC=1 # rounding only supported with sae
ROUNDC=4 SAE=1 VL128 -> LLRC=3 BCRC=1 # rounding only supported with sae

# everything else (must be VL512)
ROUNDC=0 SAE=1 VL512 -> LLRC=0 BCRC=1 # sae only, no rounding 
ROUNDC=1 SAE=1 VL512 -> LLRC=0 BCRC=1 # rounding only supported with sae
ROUNDC=2 SAE=1 VL512 -> LLRC=1 BCRC=1 # rounding only supported with sae
ROUNDC=3 SAE=1 VL512 -> LLRC=2 BCRC=1 # rounding only supported with sae
ROUNDC=4 SAE=1 VL512 -> LLRC=3 BCRC=1 # rounding only supported with sae


AVX512_EVEX_BYTE3_ENC()::
ZEROING[z] LLRC[nn] BCRC[b] VEXDEST4=0 MASK[aaa] -> z_nn_b 0b1 aaa
ZEROING[z] LLRC[nn] BCRC[b] VEXDEST4=1 MASK[aaa] -> z_nn_b 0b0 aaa



#################################################
SEQUENCE NEWVEX3_ENC_BIND
    VEX_TYPE_ENC_BIND
    VEX_REXR_ENC_BIND
    VEX_REXXB_ENC_BIND
    VEX_MAP_ENC_BIND
    VEX_REG_ENC_BIND
    VEX_ESCVL_ENC_BIND

SEQUENCE  NEWVEX3_ENC_EMIT
    VEX_TYPE_ENC_EMIT
    VEX_REXR_ENC_EMIT
    VEX_REXXB_ENC_EMIT
    VEX_MAP_ENC_EMIT
    VEX_REG_ENC_EMIT
    VEX_ESCVL_ENC_EMIT



##############################################################################

AVX512_ROUND()::
ROUNDC=1 -> LLRC=0 BCRC=1 SAE=1
ROUNDC=2 -> LLRC=1 BCRC=1 SAE=1
ROUNDC=3 -> LLRC=2 BCRC=1 SAE=1
ROUNDC=4 -> LLRC=3 BCRC=1 SAE=1

SAE()::
SAE=1 -> BCRC=1
SAE=0 -> BCRC=0


EVEXR4_ONE()::
otherwise -> nothing
