mirror of
https://github.com/RPCSX/xed.git
synced 2024-11-26 21:10:29 +00:00
ffd94e705c
Change-Id: I32a6db1a17988d9df8ff69aa1672dbf08b108e8a
235 lines
7.2 KiB
Plaintext
Executable File
235 lines
7.2 KiB
Plaintext
Executable File
#BEGIN_LEGAL
|
|
#
|
|
#Copyright (c) 2016 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
|
|
# any of the things in {} can trigger the action for these
|
|
# the letters in square brackets are bound to the bits after the arrow.
|
|
# The [] brackets are like an OR-triggering function.
|
|
|
|
# For encoding, we spell out the order of the legacy prefixes and rex
|
|
# prefixes. On decode, the sequential semantics were used to zero out
|
|
# the effects of rex prefixes but that doesn't work for encode. So we
|
|
# have to make a different table for encoding.
|
|
|
|
|
|
SEQUENCE ISA_ENCODE
|
|
ISA_BINDINGS
|
|
ISA_EMIT
|
|
|
|
# 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()
|
|
OSZ_NONTERM_ENC_BIND() # OSZ must be after the instructions so that DF64 is bound (and before any prefixes obviously)
|
|
PREFIX_ENC_BIND()
|
|
REX_PREFIX_ENC_BIND()
|
|
|
|
# These emit the bits and bytes that make up the encoding
|
|
SEQUENCE ISA_EMIT
|
|
PREFIX_ENC_EMIT()
|
|
REX_PREFIX_ENC_EMIT()
|
|
INSTRUCTIONS_EMIT() # THIS TAKES CARE OF MODRM/SIB/DISP/IMM
|
|
|
|
|
|
FIXUP_EOSZ_ENC()::
|
|
mode16 EOSZ=0 -> EOSZ=1
|
|
mode32 EOSZ=0 -> EOSZ=2
|
|
mode64 EOSZ=0 -> EOSZ=2
|
|
otherwise -> nothing
|
|
|
|
FIXUP_EASZ_ENC()::
|
|
mode16 EASZ=0 -> EASZ=1
|
|
mode32 EASZ=0 -> EASZ=2
|
|
mode64 EASZ=0 -> EASZ=3
|
|
otherwise -> nothing
|
|
|
|
FIXUP_SMODE_ENC()::
|
|
mode64 SMODE=0 -> SMODE=2
|
|
mode64 SMODE=1 -> error
|
|
otherwise -> nothing
|
|
|
|
# FIXME: make ICLASS a possible field?
|
|
# Remove the segment override if any supplied, from an LEA
|
|
REMOVE_SEGMENT()::
|
|
AGEN=0 -> nothing
|
|
AGEN=1 -> REMOVE_SEGMENT_AGEN1()
|
|
|
|
REMOVE_SEGMENT_AGEN1()::
|
|
SEG0=@ -> nothing
|
|
SEG0=SEGe() -> error
|
|
|
|
|
|
# need to emit a segment override if the segment is not the default segment for the operation.
|
|
# These are only meant for use with the things that do not use MODRM (like xlat, A0-A3 MOVs, and the string ops).
|
|
# (MODRM encoding handles this stuff much better).
|
|
OVERRIDE_SEG0()::
|
|
SEG0=@ -> SEG_OVD=0
|
|
SEG0=XED_REG_DS -> SEG_OVD=0
|
|
SEG0=XED_REG_CS -> SEG_OVD=1
|
|
SEG0=XED_REG_ES -> SEG_OVD=3
|
|
SEG0=XED_REG_FS -> SEG_OVD=4
|
|
SEG0=XED_REG_GS -> SEG_OVD=5
|
|
SEG0=XED_REG_SS -> SEG_OVD=6
|
|
|
|
OVERRIDE_SEG1()::
|
|
SEG1=@ -> SEG_OVD=0
|
|
SEG1=XED_REG_DS -> SEG_OVD=0
|
|
SEG1=XED_REG_CS -> SEG_OVD=1
|
|
SEG1=XED_REG_ES -> SEG_OVD=3
|
|
SEG1=XED_REG_FS -> SEG_OVD=4
|
|
SEG1=XED_REG_GS -> SEG_OVD=5
|
|
SEG1=XED_REG_SS -> SEG_OVD=6
|
|
|
|
|
|
|
|
REX_PREFIX_ENC()::
|
|
mode64 NOREX=0 NEEDREX=1 REXW[w] REXB[b] REXX[x] REXR[r] -> 0b0100 wrxb
|
|
mode64 NOREX=0 REX=1 REXW[w] REXB[b] REXX[x] REXR[r] -> 0b0100 wrxb
|
|
mode64 NOREX=0 REXW[w]=1 REXB[b] REXX[x] REXR[r] -> 0b0100 wrxb
|
|
mode64 NOREX=0 REXW[w] REXB[b]=1 REXX[x] REXR[r] -> 0b0100 wrxb
|
|
mode64 NOREX=0 REXW[w] REXB[b] REXX[x]=1 REXR[r] -> 0b0100 wrxb
|
|
mode64 NOREX=0 REXW[w] REXB[b] REXX[x] REXR[r]=1 -> 0b0100 wrxb
|
|
mode64 NOREX=1 NEEDREX=1 -> error
|
|
mode64 NOREX=1 REX=1 -> error
|
|
mode64 NOREX=1 REXW=1 -> error
|
|
mode64 NOREX=1 REXB=1 -> error
|
|
mode64 NOREX=1 REXX=1 -> error
|
|
mode64 NOREX=1 REXR=1 -> error
|
|
mode64 NEEDREX=0 REX=0 REXW=0 REXB=0 REXX=0 REXR=0 -> nothing
|
|
|
|
# If any REX bit shows up in 32 or 16b mode, we have an error. ensure everything is zero
|
|
mode32 REX=0 REXW=0 REXB=0 REXX=0 REXR=0 -> nothing
|
|
mode16 REX=0 REXW=0 REXB=0 REXX=0 REXR=0 -> nothing
|
|
|
|
# or die...1
|
|
otherwise -> error
|
|
|
|
# This checks that we didn't try to use a byte register that requires
|
|
# we do not have a rex with something else that requires we have a REX
|
|
# prefix.
|
|
|
|
# FIXME: need to allow repeated prefixes
|
|
|
|
# FIXME: optionally allow for prefix order to be specified (from decode)
|
|
|
|
PREFIX_ENC()::
|
|
# create an "OR" of REFINING=2 and REP=2
|
|
REP=2 -> 0xf2 no_return
|
|
REP=3 -> 0xf3 no_return
|
|
#
|
|
66_prefix -> 0x66 no_return
|
|
67_prefix -> 0x67 no_return
|
|
lock_prefix -> 0xf0 no_return
|
|
fs_prefix -> 0x64 no_return
|
|
gs_prefix -> 0x65 no_return
|
|
####################################################
|
|
mode64 HINT=3 -> 0x2e no_return
|
|
mode64 HINT=4 -> 0x3e no_return
|
|
#####################################################
|
|
not64 cs_prefix -> 0x2e no_return
|
|
not64 HINT=3 -> 0x2e no_return
|
|
not64 ds_prefix -> 0x3e no_return
|
|
not64 HINT=4 -> 0x3e no_return
|
|
not64 es_prefix -> 0x26 no_return
|
|
not64 ss_prefix -> 0x36 no_return
|
|
otherwise -> nothing
|
|
|
|
|
|
##########################################################################
|
|
#
|
|
#
|
|
# This is the encode version. It just sets DF64 for later use by the
|
|
# OSZ_NONTERM_ENC() nonterminal.
|
|
#
|
|
DF64()::
|
|
mode16 -> nothing
|
|
mode32 -> nothing
|
|
mode64 -> DF64=1 ### EOSZ=3 -- removed EOSZ=3 because it broke encoding pop 16b dx in 64b mode.
|
|
|
|
#
|
|
# If an instruction pattern sets W to zero or 1, we make sure it also
|
|
# sets SKIP_OSZ=1 so that we do not do any overwrite of that value for
|
|
# the EOSZ computation.
|
|
#
|
|
OSZ_NONTERM_ENC()::
|
|
mode16 EOSZ=1 -> nothing
|
|
mode16 EOSZ=2 DF32=1 -> nothing
|
|
|
|
# We don't use SKIP_OSZ=1 with the MOV_CR instructions but this is
|
|
# here for completeness.
|
|
mode16 EOSZ=2 DF32=0 SKIP_OSZ=1 -> nothing
|
|
mode16 EOSZ=2 DF32=0 SKIP_OSZ=0 -> 66_prefix
|
|
|
|
mode32 EOSZ=1 SKIP_OSZ=1 -> nothing
|
|
mode32 EOSZ=1 SKIP_OSZ=0 -> 66_prefix
|
|
|
|
mode32 EOSZ=2 -> nothing
|
|
|
|
mode64 EOSZ=1 SKIP_OSZ=1 -> nothing
|
|
mode64 EOSZ=1 SKIP_OSZ=0 -> 66_prefix
|
|
|
|
mode64 EOSZ=2 DF64=1 -> error
|
|
mode64 EOSZ=2 DF64=0 -> nothing
|
|
mode64 EOSZ=3 DF64=1 -> nothing
|
|
|
|
mode64 EOSZ=3 DF64=0 SKIP_OSZ=1 -> nothing
|
|
mode64 EOSZ=3 DF64=0 SKIP_OSZ=0 -> REXW=1
|
|
|
|
|
|
# The REFINING66() decode version is required for when we have a 66
|
|
# prefix that should not change the EOSZ. The REFINING66() decode
|
|
# nonterminal restores that EOSZ.
|
|
#
|
|
# This one, the REFINING66() encode version is required for
|
|
# compatibility, but it doesn't do anything. The EOSZ is an input to
|
|
# the endoder.
|
|
#
|
|
# Turn off the REP prefix in case we are switching forms.
|
|
REFINING66()::
|
|
otherwise -> nothing # norep works too
|
|
IGNORE66()::
|
|
otherwise -> nothing
|
|
|
|
# Same for IMMUNE66() used for sttni/cmpxchg8B/cmpxchg16b. We do not want to emit a 66 prefix in 32b mode
|
|
IMMUNE66()::
|
|
mode16 -> EOSZ=2 DF32=1
|
|
otherwise -> nothing
|
|
|
|
|
|
IMMUNE66_LOOP64()::
|
|
otherwise -> nothing
|
|
|
|
IMMUNE_REXW()::
|
|
otherwise -> nothing
|
|
|
|
CR_WIDTH()::
|
|
mode16 -> DF32=1 EOSZ=2
|
|
mode32 -> nothing
|
|
mode64 -> DF64=1 EOSZ=3
|
|
|
|
FORCE64()::
|
|
otherwise -> DF64=1 EOSZ=3
|
|
|
|
|
|
# the prefix encoder does all the required work.
|
|
BRANCH_HINT()::
|
|
otherwise -> nothing
|
|
|
|
# end of xed-prefixes-encode.txt
|
|
##########################################################################
|