#BEGIN_LEGAL # #Copyright (c) 2023 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 # Decoder ring # @ = null = invalid register # * = any valid register or value for this field # nothing = encode nothing in this case # error = cannot encode SEQUENCE MODRM_BIND SIB_REQUIRED_ENCODE_BIND() SIBSCALE_ENCODE_BIND() SIBINDEX_ENCODE_BIND() SIBBASE_ENCODE_BIND() MODRM_RM_ENCODE_BIND() MODRM_MOD_ENCODE_BIND() SEGMENT_DEFAULT_ENCODE_BIND() SEGMENT_ENCODE_BIND() SIB_NT_BIND() # FIXME 2007-06-30 DISP_NT_BIND() SEQUENCE MODRM_EMIT #MODRM_NT_EMIT() # FIXME: 2007-06-30 the instruction will emit this as part of the INSTRUCTIONS NT SIB_NT_EMIT() DISP_NT_EMIT() SEGMENT_DEFAULT_ENCODE():: BASE0=rIPa() -> nothing # no segment for RIP/EIP BASE0=ArSP() -> default_ss # default to SS BASE0=ArBP() -> default_ss # default to SS BASE0=@ -> default_ds # default to DS -- baseless # BASE0=ArAX() -> default_ds # everything else defaults to DS BASE0=ArCX() -> default_ds BASE0=ArDX() -> default_ds BASE0=ArBX() -> default_ds BASE0=ArSI() -> default_ds BASE0=ArDI() -> default_ds BASE0=Ar8() -> default_ds BASE0=Ar9() -> default_ds BASE0=Ar10() -> default_ds BASE0=Ar11() -> default_ds BASE0=Ar12() -> default_ds BASE0=Ar13() -> default_ds BASE0=Ar14() -> default_ds BASE0=Ar15() -> default_ds SEGMENT_ENCODE():: default_ss SEG0=@ -> no_seg_prefix # was "nothing" 2007-0x08-0x14 # assume this is what the user wanted default_ss SEG0=XED_REG_CS -> cs_prefix default_ss SEG0=XED_REG_DS -> ds_prefix default_ss SEG0=XED_REG_SS -> no_seg_prefix # was "nothing" 2007-0x08-0x14 # matches default default_ss SEG0=XED_REG_ES -> es_prefix default_ss SEG0=XED_REG_FS -> fs_prefix default_ss SEG0=XED_REG_GS -> gs_prefix # default_ds SEG0=@ -> no_seg_prefix # was "nothing" 2007-0x08-0x14 # assume this is what the user wanted default_ds SEG0=XED_REG_CS -> cs_prefix default_ds SEG0=XED_REG_DS -> no_seg_prefix # was "nothing" 2007-0x08-0x14 # matches default default_ds SEG0=XED_REG_SS -> ss_prefix default_ds SEG0=XED_REG_ES -> es_prefix default_ds SEG0=XED_REG_FS -> fs_prefix default_ds SEG0=XED_REG_GS -> gs_prefix otherwise -> no_seg_prefix # was "nothing" 2007-0x08-0x14 SIB_REQUIRED_ENCODE():: eamode32 INDEX=GPR32e() -> NEED_SIB=1 eamode64 INDEX=GPR64e() -> NEED_SIB=1 # base-less memop in 64b mode requires a SIB eamode64 BASE0=@ DISP_WIDTH=32 -> NEED_SIB=1 eamode32 mode64 BASE0=@ DISP_WIDTH=32 -> NEED_SIB=1 eamode32 mode16 -> nothing eamode32 mode32 -> nothing # Denote the need of a SIB byte if base is rSP or r12 eanot16 BASE0=ArSP() -> NEED_SIB=1 eanot16 BASE0=Ar12() -> NEED_SIB=1 # When the displacement is omitted, we supply one for these r13 and rBP. #eanot16 BASE0=ArBP() DISP_WIDTH=0 -> NEED_SIB=1 #eanot16 BASE0=Ar13() DISP_WIDTH=0 -> NEED_SIB=1 otherwise -> nothing # FIXME: could set NEED_SIB=0 SIBBASE_ENCODE():: NEED_SIB=0 -> nothing NEED_SIB=1 -> SIBBASE_ENCODE_SIB1() SIBBASE_ENCODE_SIB1():: BASE0=ArAX() -> SIBBASE=0 REXB=0 BASE0=Ar8() -> SIBBASE=0 REXB=1 BASE0=ArCX() -> SIBBASE=1 REXB=0 BASE0=Ar9() -> SIBBASE=1 REXB=1 BASE0=ArDX() -> SIBBASE=2 REXB=0 BASE0=Ar10() -> SIBBASE=2 REXB=1 BASE0=ArBX() -> SIBBASE=3 REXB=0 BASE0=Ar11() -> SIBBASE=3 REXB=1 BASE0=ArSP() -> SIBBASE=4 REXB=0 BASE0=Ar12() -> SIBBASE=4 REXB=1 # The mod values are really gotten by the MOD rule, only requiring one # addition. ## BAD MODIFIES DISP! NEED_SIB=1 BASE0=@ DISP_WIDTH=8 -> SIBBASE=5 REXB=0 DISP_WIDTH=32 # MOD=0 BASE0=@ -> DISP_WIDTH_32() SIBBASE=5 REXB=0 # MOD=0 # The MOD rule handles the DISP arg modification for rBP and r13 BASE0=ArBP() -> DISP_WIDTH_0_8_32() SIBBASE=5 REXB=0 # MOD=1 # ARG MODIFICATION LATER IN MOD RULE # NEED_SIB=1 BASE0=@ DISP_WIDTH=32 -> SIBBASE=5 REXB=0 # MOD=0 redundant with the above # The MOD rule handles the DISP arg modification for rBP and r13 BASE0=Ar13() -> DISP_WIDTH_0_8_32() SIBBASE=5 REXB=1 # MOD=1 # ARG MODIFICATION LATER IN MOD RULE BASE0=ArSI() -> SIBBASE=6 REXB=0 BASE0=Ar14() -> SIBBASE=6 REXB=1 BASE0=ArDI() -> SIBBASE=7 REXB=0 BASE0=Ar15() -> SIBBASE=7 REXB=1 otherwise -> error # BASE0 was some other register SIBINDEX_ENCODE():: NEED_SIB=0 -> nothing NEED_SIB=1 -> SIBINDEX_ENCODE_SIB1() SIBINDEX_ENCODE_SIB1():: INDEX=ArAX() -> SIBINDEX=0 REXX=0 INDEX=Ar8() -> SIBINDEX=0 REXX=1 INDEX=ArCX() -> SIBINDEX=1 REXX=0 INDEX=Ar9() -> SIBINDEX=1 REXX=1 INDEX=ArDX() -> SIBINDEX=2 REXX=0 INDEX=Ar10() -> SIBINDEX=2 REXX=1 INDEX=ArBX() -> SIBINDEX=3 REXX=0 INDEX=Ar11() -> SIBINDEX=3 REXX=1 INDEX=@ -> SIBINDEX=4 REXX=0 # the "no index" option INDEX=Ar12() -> SIBINDEX=4 REXX=1 INDEX=ArBP() -> SIBINDEX=5 REXX=0 INDEX=Ar13() -> SIBINDEX=5 REXX=1 INDEX=ArSI() -> SIBINDEX=6 REXX=0 INDEX=Ar14() -> SIBINDEX=6 REXX=1 INDEX=ArDI() -> SIBINDEX=7 REXX=0 INDEX=Ar15() -> SIBINDEX=7 REXX=1 otherwise -> error # INDEX was some other register SIBSCALE_ENCODE():: NEED_SIB=0 -> nothing NEED_SIB=1 SCALE=0 -> SIBSCALE=0 # this allows for default unset scales NEED_SIB=1 SCALE=1 -> SIBSCALE=0 NEED_SIB=1 SCALE=2 -> SIBSCALE=1 NEED_SIB=1 SCALE=4 -> SIBSCALE=2 NEED_SIB=1 SCALE=8 -> SIBSCALE=3 otherwise -> error # SCALE was some other value ############################################################################## MODRM_MOD_ENCODE():: eamode16 DISP_WIDTH=0 -> MODRM_MOD_EA16_DISP0() eamode16 DISP_WIDTH=8 -> MODRM_MOD_EA16_DISP8() eamode16 DISP_WIDTH=16 -> MODRM_MOD_EA16_DISP16() eamode16 DISP_WIDTH=32 -> ERROR() eamode16 DISP_WIDTH=64 -> ERROR() eamode32 DISP_WIDTH=0 -> MODRM_MOD_EA32_DISP0() eamode32 DISP_WIDTH=8 -> MODRM_MOD_EA32_DISP8() eamode32 DISP_WIDTH=16 -> ERROR() eamode32 DISP_WIDTH=32 -> MODRM_MOD_EA32_DISP32() eamode32 DISP_WIDTH=64 -> ERROR() eamode64 DISP_WIDTH=0 -> MODRM_MOD_EA64_DISP0() eamode64 DISP_WIDTH=8 -> MODRM_MOD_EA64_DISP8() eamode64 DISP_WIDTH=16 -> ERROR() eamode64 DISP_WIDTH=32 -> MODRM_MOD_EA64_DISP32() eamode64 DISP_WIDTH=64 -> ERROR() ############################################################################## #### EAMODE16 ############################################################################## MODRM_MOD_EA16_DISP0():: BASE0=XED_REG_BX INDEX=@ -> MOD=0 BASE0=XED_REG_SI INDEX=@ -> MOD=0 BASE0=XED_REG_DI INDEX=@ -> MOD=0 BASE0=XED_REG_BP INDEX=@ -> MOD=1 DISP_WIDTH=8 DISP=0 # ARG MODIFICATION BASE0=XED_REG_BP INDEX=XED_REG_SI -> MOD=0 BASE0=XED_REG_BP INDEX=XED_REG_DI -> MOD=0 BASE0=XED_REG_BX INDEX=XED_REG_SI -> MOD=0 BASE0=XED_REG_BX INDEX=XED_REG_DI -> MOD=0 MODRM_MOD_EA16_DISP8():: BASE0=XED_REG_BX INDEX=@ -> MOD=1 BASE0=XED_REG_SI INDEX=@ -> MOD=1 BASE0=XED_REG_DI INDEX=@ -> MOD=1 BASE0=XED_REG_BP INDEX=@ -> MOD=1 BASE0=XED_REG_BP INDEX=XED_REG_SI -> MOD=1 BASE0=XED_REG_BP INDEX=XED_REG_DI -> MOD=1 BASE0=XED_REG_BX INDEX=XED_REG_SI -> MOD=1 BASE0=XED_REG_BX INDEX=XED_REG_DI -> MOD=1 MODRM_MOD_EA16_DISP16():: BASE0=@ INDEX=@ -> MOD=0 BASE0=XED_REG_BX INDEX=@ -> MOD=2 BASE0=XED_REG_SI INDEX=@ -> MOD=2 BASE0=XED_REG_DI INDEX=@ -> MOD=2 BASE0=XED_REG_BP INDEX=@ -> MOD=2 BASE0=XED_REG_BP INDEX=XED_REG_SI -> MOD=2 BASE0=XED_REG_BP INDEX=XED_REG_DI -> MOD=2 BASE0=XED_REG_BX INDEX=XED_REG_SI -> MOD=2 BASE0=XED_REG_BX INDEX=XED_REG_DI -> MOD=2 ############################################################################## #### EAMODE32 ############################################################################## MODRM_MOD_EA32_DISP0():: # Add a fake 1B displacement to rBP and r13 if they do not have one already. BASE0=XED_REG_EBP mode32 -> MOD=1 DISP_WIDTH=8 DISP=0 # ARG MODIFICATION BASE0=XED_REG_EBP mode64 -> MOD=1 DISP_WIDTH=8 DISP=0 # ARG MODIFICATION BASE0=XED_REG_R13D mode64 -> MOD=1 DISP_WIDTH=8 DISP=0 # ARG MODIFICATION # All these 32b and 64b base regs can handle no displacement BASE0=XED_REG_EAX mode32 -> MOD=0 BASE0=XED_REG_EBX mode32 -> MOD=0 BASE0=XED_REG_ECX mode32 -> MOD=0 BASE0=XED_REG_EDX mode32 -> MOD=0 BASE0=XED_REG_ESI mode32 -> MOD=0 BASE0=XED_REG_EDI mode32 -> MOD=0 BASE0=XED_REG_ESP mode32 -> MOD=0 # our choice to use MOD=0 (w/sib) BASE0=XED_REG_EAX mode64 -> MOD=0 BASE0=XED_REG_EBX mode64 -> MOD=0 BASE0=XED_REG_ECX mode64 -> MOD=0 BASE0=XED_REG_EDX mode64 -> MOD=0 BASE0=XED_REG_ESI mode64 -> MOD=0 BASE0=XED_REG_EDI mode64 -> MOD=0 BASE0=XED_REG_ESP mode64 -> MOD=0 # our choice to use MOD=0 (w/sib) BASE0=XED_REG_R8D mode64 -> MOD=0 BASE0=XED_REG_R9D mode64 -> MOD=0 BASE0=XED_REG_R10D mode64 -> MOD=0 BASE0=XED_REG_R11D mode64 -> MOD=0 BASE0=XED_REG_R12D mode64 -> MOD=0 # our choice to use MOD=0 (w/sib) BASE0=XED_REG_R14D mode64 -> MOD=0 BASE0=XED_REG_R15D mode64 -> MOD=0 MODRM_MOD_EA32_DISP8():: otherwise -> MOD=1 # might use SIB MODRM_MOD_EA32_DISP32():: BASE0=@ -> MOD=0 #no base (handles NEED_SIB=1 case) BASE0=GPR32e() -> MOD=2 #some base, not RIP, might use SIB BASE0=rIPa() mode64 -> MOD=0 ############################################################################## #### EAMODE64 ############################################################################## MODRM_MOD_EA64_DISP0():: BASE0=XED_REG_EIP -> MOD=0 DISP_WIDTH=32 DISP=0 # base eip BASE0=XED_REG_RIP -> MOD=0 DISP_WIDTH=32 DISP=0 # base rip BASE0=XED_REG_RBP -> MOD=1 DISP_WIDTH=8 DISP=0 # ARG MODIFICATION BASE0=XED_REG_R13 -> MOD=1 DISP_WIDTH=8 DISP=0 # ARG MODIFICATION BASE0=XED_REG_RAX -> MOD=0 BASE0=XED_REG_RBX -> MOD=0 BASE0=XED_REG_RCX -> MOD=0 BASE0=XED_REG_RDX -> MOD=0 BASE0=XED_REG_RSI -> MOD=0 BASE0=XED_REG_RDI -> MOD=0 BASE0=XED_REG_RSP -> MOD=0 BASE0=XED_REG_R8 -> MOD=0 BASE0=XED_REG_R9 -> MOD=0 BASE0=XED_REG_R10 -> MOD=0 BASE0=XED_REG_R11 -> MOD=0 BASE0=XED_REG_R12 -> MOD=0 BASE0=XED_REG_R14 -> MOD=0 BASE0=XED_REG_R15 -> MOD=0 MODRM_MOD_EA64_DISP8():: BASE0=GPR64e() -> MOD=1 MODRM_MOD_EA64_DISP32():: BASE0=@ -> MOD=0 #no base, NEED_SIB=1 required (provided elsewhere) BASE0=XED_REG_EIP -> MOD=0 #base eip BASE0=XED_REG_RIP -> MOD=0 #base rip BASE0=XED_REG_RAX -> MOD=2 BASE0=XED_REG_RBX -> MOD=2 BASE0=XED_REG_RCX -> MOD=2 BASE0=XED_REG_RDX -> MOD=2 BASE0=XED_REG_RSI -> MOD=2 BASE0=XED_REG_RDI -> MOD=2 BASE0=XED_REG_RSP -> MOD=2 # NEED_SIB=1 required (and is provided elsewhere) BASE0=XED_REG_RBP -> MOD=2 BASE0=XED_REG_R8 -> MOD=2 BASE0=XED_REG_R9 -> MOD=2 BASE0=XED_REG_R10 -> MOD=2 BASE0=XED_REG_R11 -> MOD=2 BASE0=XED_REG_R12 -> MOD=2 # NEED_SIB=1 required (and is provided elsewhere) BASE0=XED_REG_R13 -> MOD=2 BASE0=XED_REG_R14 -> MOD=2 BASE0=XED_REG_R15 -> MOD=2 ######################################################################################################## #If we didn't already encode the base in the SIB! MODRM_RM_ENCODE():: eamode16 NEED_SIB=0 -> MODRM_RM_ENCODE_EA16_SIB0() eamode32 NEED_SIB=0 -> MODRM_RM_ENCODE_EA32_SIB0() eamode64 NEED_SIB=0 -> MODRM_RM_ENCODE_EA64_SIB0() eanot16 NEED_SIB=1 -> MODRM_RM_ENCODE_EANOT16_SIB1() ############################################# MODRM_RM_ENCODE_EA16_SIB0():: BASE0=XED_REG_BX INDEX=XED_REG_SI -> RM=0 BASE0=XED_REG_BX INDEX=XED_REG_DI -> RM=1 BASE0=XED_REG_BP INDEX=XED_REG_SI -> RM=2 BASE0=XED_REG_BP INDEX=XED_REG_DI -> RM=3 BASE0=XED_REG_SI INDEX=@ -> RM=4 BASE0=XED_REG_DI INDEX=@ -> RM=5 BASE0=@ INDEX=@ -> DISP_WIDTH_16() RM=6 # for BP without an index, we add an imm8=0 when encoding the MOD BASE0=XED_REG_BP INDEX=@ -> DISP_WIDTH_0_8_16() RM=6 BASE0=XED_REG_BX INDEX=@ -> RM=7 MODRM_RM_ENCODE_EA64_SIB0():: BASE0=XED_REG_RAX -> RM=0 REXB=0 BASE0=XED_REG_R8 -> RM=0 REXB=1 BASE0=XED_REG_RCX -> RM=1 REXB=0 BASE0=XED_REG_R9 -> RM=1 REXB=1 BASE0=XED_REG_RDX -> RM=2 REXB=0 BASE0=XED_REG_R10 -> RM=2 REXB=1 BASE0=XED_REG_RBX -> RM=3 REXB=0 BASE0=XED_REG_R11 -> RM=3 REXB=1 BASE0=XED_REG_RSI -> RM=6 REXB=0 BASE0=XED_REG_R14 -> RM=6 REXB=1 BASE0=XED_REG_RDI -> RM=7 REXB=0 BASE0=XED_REG_R15 -> RM=7 REXB=1 # case RM=5 is tricky. The mode,base and disp width play a role BASE0=@ -> DISP_WIDTH_32() RM=5 # not setting REXB FIXME? # for rBP without a disp, we add a 1B disp so MOD will be 1 BASE0=XED_REG_RBP -> DISP_WIDTH_0_8_32() RM=5 REXB=0 # When we do the MOD encoding, we fix the displacement at 4B. BASE0=XED_REG_RIP -> RM=5 # not setting REXB FIXME? BASE0=XED_REG_EIP -> RM=5 # not setting REXB FIXME? # for r13 without a disp, we add a 1B disp so MOD will be 1 BASE0=XED_REG_R13 -> DISP_WIDTH_0_8_32() RM=5 REXB=1 MODRM_RM_ENCODE_EA32_SIB0():: BASE0=XED_REG_EAX -> RM=0 REXB=0 BASE0=XED_REG_R8D -> RM=0 REXB=1 BASE0=XED_REG_ECX -> RM=1 REXB=0 BASE0=XED_REG_R9D -> RM=1 REXB=1 BASE0=XED_REG_EDX -> RM=2 REXB=0 BASE0=XED_REG_R10D -> RM=2 REXB=1 BASE0=XED_REG_EBX -> RM=3 REXB=0 BASE0=XED_REG_R11D -> RM=3 REXB=1 BASE0=XED_REG_ESI -> RM=6 REXB=0 BASE0=XED_REG_R14D -> RM=6 REXB=1 BASE0=XED_REG_EDI -> RM=7 REXB=0 BASE0=XED_REG_R15D -> RM=7 REXB=1 # case RM=5 is tricky. The mode,base and disp width play a role BASE0=@ -> DISP_WIDTH_32() RM=5 # not setting REXB FIXME? # for rBP without a disp, we add a 1B disp so MOD will be 1 BASE0=XED_REG_EBP -> DISP_WIDTH_0_8_32() RM=5 REXB=0 # for r13 without a disp, we add a 1B disp so MOD will be 1 BASE0=XED_REG_R13D -> DISP_WIDTH_0_8_32() RM=5 REXB=1 BASE0=XED_REG_RIP mode64 -> RM=5 BASE0=XED_REG_EIP mode64 -> RM=5 MODRM_RM_ENCODE_EANOT16_SIB1():: otherwise -> RM=4 # SIB will specify the REXB etc. ############################################# # These are good, seemingly: # FIXME: these are semi-redundant with field bindings that I need for decode. # I was thinking about using something like: # MODRM[mm,rrr,nnn] & SIB[ss,iii,bbb] # coupled with: # MODRM = (MOD,2), (REG,3), (RM,3) # SIB = (SIBSCALE,2), (SIBINDEX,3), (SIBBASE,3) #FIXME: don't require =*??? #FIXME: handle "nothing" option ## SIB_EMIT():: ## NEED_SIB=1 SIBBASE[bbb]=* SIBSCALE[ss]=* SIBINDEX[iii]=* -> ss_iii_bbb ## NEED_SIB=0 -> nothing ## ## MODRM_EMIT():: ## MODRM=1 MOD[xx]=* REG[rrr]=* RM[mmm]=* -> xx_rrr_mmm ## MODRM=0 -> nothing # ... OR ... SIB_NT():: NEED_SIB=1 SIBBASE[bbb] SIBSCALE[ss] SIBINDEX[iii] -> ss_iii_bbb NEED_SIB=0 -> nothing # 2 bytes storage DISP_NT():: #DISP_WIDTH=0 -> nothing DISP_WIDTH=8 DISP[d/8] -> d/8 DISP_WIDTH=16 DISP[d/16] -> d/16 DISP_WIDTH=32 DISP[d/32] -> d/32 DISP_WIDTH=64 DISP[d/64] -> d/64 otherwise -> nothing ERROR():: otherwise -> ERROR=XED_ERROR_GENERAL_ERROR DISP_WIDTH_0():: DISP_WIDTH=0 -> nothing DISP_WIDTH_8():: DISP_WIDTH=8 -> nothing DISP_WIDTH_16():: DISP_WIDTH=16 -> nothing DISP_WIDTH_32():: DISP_WIDTH=32 -> nothing DISP_WIDTH_0_8_16():: DISP_WIDTH=0 -> nothing DISP_WIDTH=8 -> nothing DISP_WIDTH=16 -> nothing DISP_WIDTH_0_8_32():: DISP_WIDTH=0 -> nothing DISP_WIDTH=8 -> nothing DISP_WIDTH=32 -> nothing