GP-1255: Allowing 32-bit x86 disassembly in x86-64 (WoW64).

This commit is contained in:
Dan 2021-08-25 16:02:35 -04:00
parent e2ea7320e1
commit 25801da834
20 changed files with 840 additions and 509 deletions

View File

@ -344,6 +344,11 @@ public class DebuggerListingProvider extends CodeViewerProvider {
return current.isAliveAndPresent();
}
@Override
public boolean isDynamicListing() {
return true;
}
@Override
public String getWindowGroup() {
//TODO: Overriding this to align disconnected providers

View File

@ -71,20 +71,15 @@ public class DbgengX64DisassemblyInject implements DisassemblyInject {
}
Mode mode = modes.iterator().next();
Language lang = trace.getBaseLanguage();
Register addrsizeReg = lang.getRegister("addrsize");
Register opsizeReg = lang.getRegister("opsize");
Register longModeReg = lang.getRegister("longMode");
ProgramContextImpl context = new ProgramContextImpl(lang);
lang.applyContextSettings(context);
RegisterValue ctxVal = context.getDisassemblyContext(first.getMinAddress());
RegisterValue ctxVal = new RegisterValue(context.getBaseContextRegister());
if (mode == Mode.X64) {
command.setInitialContext(ctxVal
.assign(addrsizeReg, BigInteger.TWO)
.assign(opsizeReg, BigInteger.TWO));
command.setInitialContext(ctxVal.assign(longModeReg, BigInteger.ONE));
}
else if (mode == Mode.X86) {
command.setInitialContext(ctxVal
.assign(addrsizeReg, BigInteger.ONE)
.assign(opsizeReg, BigInteger.ONE));
command.setInitialContext(ctxVal.assign(longModeReg, BigInteger.ZERO));
}
// Shouldn't ever get anything else.
}

View File

@ -25,8 +25,7 @@ import org.junit.*;
import com.google.common.collect.Range;
import ghidra.app.cmd.disassemble.ArmDisassembleCommand;
import ghidra.app.cmd.disassemble.MipsDisassembleCommand;
import ghidra.app.cmd.disassemble.*;
import ghidra.program.database.ProgramBuilder;
import ghidra.program.disassemble.Disassembler;
import ghidra.program.model.address.AddressOverflowException;
@ -215,4 +214,74 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn
assertEquals("_nop", cu2.toString());
}
}
@TestLanguage(ProgramBuilder._X64)
public void test64BitX86DBTrace() throws Exception {
try (UndoableTransaction tid = b.startTransaction()) {
DBTraceMemoryManager memory = b.trace.getMemoryManager();
memory.createRegion(".text", 0, b.range(0x00400000, 0x00400fff));
memory.putBytes(0, b.addr(0x00400000), b.buf(
// MOV RCX,RAX; Same encoding as DEC EAX; MOV ECX,EAX outside long mode
0x48, 0x89, 0xc1));
AddressSet restricted = new AddressSet(b.addr(0x00400000), b.addr(0x00400002));
X86_64DisassembleCommand x86Dis =
new X86_64DisassembleCommand(b.addr(0x00400000), restricted, false);
x86Dis.applyTo(b.trace.getFixedProgramView(0), TaskMonitor.DUMMY);
DBTraceCodeUnitsMemoryView cuManager = b.trace.getCodeManager().codeUnits();
CodeUnit cu1 = cuManager.getAt(0, b.addr(0x00400000));
assertEquals("MOV RCX,RAX", cu1.toString());
}
}
@Test
@TestLanguage(ProgramBuilder._X64)
public void test32BitX64CompatDBTrace() throws Exception {
try (UndoableTransaction tid = b.startTransaction()) {
DBTraceMemoryManager memory = b.trace.getMemoryManager();
memory.createRegion(".text", 0, b.range(0x00400000, 0x00400fff));
memory.putBytes(0, b.addr(0x00400000), b.buf(
// DEC EAX; but REX.W if context not heeded
0x48,
// MOV ECX,EAX
0x89, 0xc1));
AddressSet restricted = new AddressSet(b.addr(0x00400000), b.addr(0x00400002));
X86_64DisassembleCommand x86Dis =
new X86_64DisassembleCommand(b.addr(0x00400000), restricted, true);
x86Dis.applyTo(b.trace.getFixedProgramView(0), TaskMonitor.DUMMY);
DBTraceCodeUnitsMemoryView cuManager = b.trace.getCodeManager().codeUnits();
CodeUnit cu1 = cuManager.getAt(0, b.addr(0x00400000));
assertEquals("DEC EAX", cu1.toString());
CodeUnit cu2 = cuManager.getAt(0, b.addr(0x00400001));
assertEquals("MOV ECX,EAX", cu2.toString());
}
}
@Test
@TestLanguage(ProgramBuilder._X86)
public void test32BitX86DBTrace() throws Exception {
try (UndoableTransaction tid = b.startTransaction()) {
DBTraceMemoryManager memory = b.trace.getMemoryManager();
memory.createRegion(".text", 0, b.range(0x00400000, 0x00400fff));
memory.putBytes(0, b.addr(0x00400000), b.buf(
// DEC EAX
0x48,
// MOV ECX,EAX
0x89, 0xc1));
AddressSet restricted = new AddressSet(b.addr(0x00400000), b.addr(0x00400002));
DisassembleCommand dis =
new DisassembleCommand(b.addr(0x00400000), restricted, true);
dis.applyTo(b.trace.getFixedProgramView(0), TaskMonitor.DUMMY);
DBTraceCodeUnitsMemoryView cuManager = b.trace.getCodeManager().codeUnits();
CodeUnit cu1 = cuManager.getAt(0, b.addr(0x00400000));
assertEquals("DEC EAX", cu1.toString());
CodeUnit cu2 = cuManager.getAt(0, b.addr(0x00400001));
assertEquals("MOV ECX,EAX", cu2.toString());
}
}
}

View File

@ -20,8 +20,7 @@ import ghidra.framework.cmd.BackgroundCommand;
import ghidra.framework.model.DomainObject;
import ghidra.program.disassemble.*;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Register;
import ghidra.program.model.lang.RegisterValue;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryBlock;
@ -46,14 +45,15 @@ public class DisassembleCommand extends BackgroundCommand {
private int alignment; // required instruction alignment for the last doDisassembly
protected boolean disassemblyPerformed; // if true don't report start problems
protected String languageError; // non-null to indicate unsupported language
protected boolean unalignedStart;
protected boolean nonExecutableStart;
/**
* Constructor for DisassembleCommand.
*
* @param start Address to start disassembly.
* @param restrictedSet addresses that can be disassembled.
* a null set implies no restrictions
* @param restrictedSet addresses that can be disassembled. a null set implies no restrictions
* @param followFlow true means the disassembly should follow flow
*/
public DisassembleCommand(Address start, AddressSetView restrictedSet, boolean followFlow) {
@ -62,22 +62,22 @@ public class DisassembleCommand extends BackgroundCommand {
}
/**
* Constructor for DisassembleCommand.
* @param startSet set of addresses to be the start of a disassembly. The
* Command object will attempt to start a disassembly at each address in this set.
* @param restrictedSet addresses that can be disassembled.
* a null set implies no restrictions
*/
* Constructor for DisassembleCommand.
*
* @param startSet set of addresses to be the start of a disassembly. The Command object will
* attempt to start a disassembly at each address in this set.
* @param restrictedSet addresses that can be disassembled. a null set implies no restrictions
*/
public DisassembleCommand(AddressSetView startSet, AddressSetView restrictedSet) {
this(startSet, restrictedSet, true);
}
/**
* Constructor for DisassembleCommand.
* @param startSet set of addresses to be the start of a disassembly. The
* Command object will attempt to start a disassembly at each address in this set.
* @param restrictedSet addresses that can be disassembled.
* a null set implies no restrictions
*
* @param startSet set of addresses to be the start of a disassembly. The Command object will
* attempt to start a disassembly at each address in this set.
* @param restrictedSet addresses that can be disassembled. a null set implies no restrictions
*/
public DisassembleCommand(AddressSetView startSet, AddressSetView restrictedSet,
boolean followFlow) {
@ -93,11 +93,12 @@ public class DisassembleCommand extends BackgroundCommand {
}
/**
* Allows the disassembler context to be seeded for the various disassembly start
* points which may be encountered using the future flow state of the specified seedContext.
* Any initial context set via the {@link #setInitialContext(RegisterValue)} method will take
* precedence when combined with any seed values.
* The seedContext should remain unchanged while disassembler command is actively running.
* Allows the disassembler context to be seeded for the various disassembly start points which
* may be encountered using the future flow state of the specified seedContext. Any initial
* context set via the {@link #setInitialContext(RegisterValue)} method will take precedence
* when combined with any seed values. The seedContext should remain unchanged while
* disassembler command is actively running.
*
* @param seedContext seed context or null
*/
public void setSeedContext(DisassemblerContextImpl seedContext) {
@ -105,11 +106,11 @@ public class DisassembleCommand extends BackgroundCommand {
}
/**
* Allows a specified initial context to be used at all start points. This value will take
* Allows a specified initial context to be used at all start points. This value will take
* precedence when combined with any individual seed context values specified by the
* {@link #setSeedContext(DisassemblerContextImpl)} method.
* The defaultSeedContext should remain unchanged while disassembler command
* is actively running.
* {@link #setSeedContext(DisassemblerContextImpl)} method. The defaultSeedContext should remain
* unchanged while disassembler command is actively running.
*
* @param initialContextValue the initial context value to set or null to clear it
*/
public void setInitialContext(RegisterValue initialContextValue) {
@ -121,8 +122,9 @@ public class DisassembleCommand extends BackgroundCommand {
}
/**
* Set code analysis enablement. By default new instructions will be
* submitted for auto-analysis.
* Set code analysis enablement. By default new instructions will be submitted for
* auto-analysis.
*
* @param enable
*/
public void enableCodeAnalysis(boolean enable) {
@ -134,6 +136,9 @@ public class DisassembleCommand extends BackgroundCommand {
if (disassemblyPerformed) {
return null;
}
if (languageError != null) {
return "The program's language is not supported: " + languageError;
}
if (nonExecutableStart) {
return "Disassembly of non-executable memory is disabled";
}
@ -312,7 +317,7 @@ public class DisassembleCommand extends BackgroundCommand {
*
* @param disassembler disassembler to use
* @param seedSet set of addresses to be disassembled
* @param mgr
* @param mgr
*
* @return addresses actually disassembled
*/
@ -335,16 +340,17 @@ public class DisassembleCommand extends BackgroundCommand {
}
/**
* Determine if intermediate analysis is required to reduce the risk of disassembling
* data regions when performing static disassembly over a contiguous range if
* addresses. This method attemps to identify this situation by checking the first
* range of disassembledSet against the startSet. Analysis will be triggered if
* startSet contains both the max address of the first range of disassembledSet
* (M where M=disassembledSet.firstRange().getMaxAddress()) and the next address
* (M.next()) which will be the next seed point.
* Determine if intermediate analysis is required to reduce the risk of disassembling data
* regions when performing static disassembly over a contiguous range if addresses. This method
* attemps to identify this situation by checking the first range of disassembledSet against the
* startSet. Analysis will be triggered if startSet contains both the max address of the first
* range of disassembledSet (M where M=disassembledSet.firstRange().getMaxAddress()) and the
* next address (M.next()) which will be the next seed point.
*
* @param mgr auto analysis manager or null if analysis disabled
* @param startSet disassembly seed points (prior to removing disassembledSet)
* @param disassembledSet last set of disassembled addresses using startSet min-address as seed point
* @param disassembledSet last set of disassembled addresses using startSet min-address as seed
* point
*/
private static void analyzeIfNeeded(AutoAnalysisManager mgr, AddressSetView startSet,
AddressSetView disassembledSet, TaskMonitor monitor) {
@ -366,6 +372,7 @@ public class DisassembleCommand extends BackgroundCommand {
/**
* Returns an address set of all instructions that were disassembled.
*
* @return an address set of all instructions that were disassembled
*/
public AddressSet getDisassembledAddressSet() {

View File

@ -0,0 +1,158 @@
/* ###
* IP: GHIDRA
*
* 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.
*/
package ghidra.app.cmd.disassemble;
import java.math.BigInteger;
import javax.help.UnsupportedOperationException;
import ghidra.framework.model.DomainObject;
import ghidra.program.disassemble.DisassemblerContextImpl;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.ProgramContext;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
* Command object for performing 64-/32-bit x86 disassembly
*
* <p>
* This generally only comes up when debugging, since there can be multiple images loaded by an
* x86-64 target. For WoW64, the images may be mixed. Thus, this command allows you to disassemble
* 64-bit or 32-bit instructions whenever the language is set to 64-bit x86.
*
* <p>
* <b>WARNING:</b> If used in static programs, i.e., not debug traces, there are some potential
* remaining issues, particularly dealing with stored context and follow-on disassembly -- typically
* called for by the analyzers. In most cases, this does not matter, since mixed 64- and 32-bit code
* in a single image is likely a niche case and can be handled via careful commands from the user.
* Nevertheless, TODO: Rework x86-64 analyzers to call the correct mode of disassembly.
*/
public class X86_64DisassembleCommand extends DisassembleCommand {
private final boolean size32Mode;
/**
* Constructor for X86_64DisassembleCommand.
*
* @param startSet set of addresses to be the start of disassembly. The Command object will
* attempt to start a disassembly at each address in this set.
* @param restrictedSet addresses that can be disassembled. a null set implies no restrictions.
* @param size32Mode pass true if disassembling in 32-bit compatibility mode, otherwise normal
* 64-bit disassembly will be performed.
*/
public X86_64DisassembleCommand(AddressSetView startSet, AddressSetView restrictedSet,
boolean size32Mode) {
super(startSet, restrictedSet, true);
this.size32Mode = size32Mode;
}
/**
* Constructor for X86_64DisassembleCommand.
*
* @param start address to be the start of a disassembly.
* @param restrictedSet addresses that can be disassembled. a null set implies no restrictions.
* @param size32Mode pass true if disassembling in 32-bit compatibility mode, otherwise normal
* 64-bit disassembly will be performed.
*/
public X86_64DisassembleCommand(Address start, AddressSetView restrictedSet,
boolean size32Mode) {
super(start, restrictedSet, true);
this.size32Mode = size32Mode;
}
@Override
public String getName() {
return "Disassemble " + (size32Mode ? "32" : "64") + "-bit x86";
}
@Override
public void setSeedContext(DisassemblerContextImpl seedContext) {
throw new UnsupportedOperationException();
}
@Override
public void setInitialContext(RegisterValue initialContextValue) {
throw new UnsupportedOperationException();
}
public static AddressSet alignSet(int alignment, AddressSetView set)
throws CancelledException {
AddressSet result = new AddressSet();
for (AddressRange range : set) {
Address min = range.getMinAddress();
long minOfffset = min.getOffset();
if (minOfffset != min.getOffset()) {
min = min.getNewAddress(minOfffset);
}
Address max = range.getMaxAddress();
long maxOffset = max.getOffset();
if (maxOffset < minOfffset) {
// skip short unaligned range
continue;
}
if (maxOffset != max.getOffset()) {
max = max.getNewAddress(maxOffset);
}
result.addRange(min, max);
}
return result;
}
@Override
synchronized public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
Program program = (Program) obj;
disassemblyPerformed = false;
unalignedStart = false;
// get the longMode register and set accordingly
ProgramContext context = program.getProgramContext();
Register longModeReg = context.getRegister("longMode");
// Indicates we're not x86-64, or the spec has changed
if (longModeReg == null) {
languageError = "Requires x86:LE:64:default";
return false;
}
RegisterValue ctx = new RegisterValue(context.getBaseContextRegister())
.assign(longModeReg, size32Mode ? BigInteger.ZERO : BigInteger.ONE);
super.setInitialContext(ctx);
try {
if (startSet != null) {
// This is identity, no?
AddressSet alignedSet = alignSet(1, startSet);
if (alignedSet.isEmpty()) {
unalignedStart = true;
return false;
}
startSet = program.getListing().getUndefinedRanges(alignedSet, true, monitor);
if (startSet.isEmpty()) {
return true;
}
}
}
catch (CancelledException e) {
return true;
}
return doDisassembly(monitor, program, 1);
}
}

View File

@ -34,22 +34,19 @@ import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;
/**
* <CODE>DisassemblerPlugin</CODE> provides functionality for dynamic disassembly,
* static disassembly.<BR>
* In dynamic disassembly disassembling begins from the
* selected addresses or if there is no selection then at the address of the
* current cursor location and attempts to continue disassembling
* through fallthroughs and along all flows from a disassembled instruction.
* For instance, if a jump instruction is disassembled then the address being
* jumped to will be disassembled. The dynamic disassembly will also follow
* data pointers to addresses containing undefined data, which is then
* disassembled.<BR>
* In static disassembly a range or set of ranges
* is given and disassembly is attempted on each range. Any defined code in the
* ranges before the static disassembly are first removed.<BR>
* <CODE>DisassemblerPlugin</CODE> provides functionality for dynamic disassembly, static
* disassembly.<BR>
* In dynamic disassembly disassembling begins from the selected addresses or if there is no
* selection then at the address of the current cursor location and attempts to continue
* disassembling through fallthroughs and along all flows from a disassembled instruction. For
* instance, if a jump instruction is disassembled then the address being jumped to will be
* disassembled. The dynamic disassembly will also follow data pointers to addresses containing
* undefined data, which is then disassembled.<BR>
* In static disassembly a range or set of ranges is given and disassembly is attempted on each
* range. Any defined code in the ranges before the static disassembly are first removed.<BR>
* <P>
* <CODE>DisassemblerPlugin</CODE> provides access to its functions as a service
* that another plugin may use and through the popup menu to the user.
* <CODE>DisassemblerPlugin</CODE> provides access to its functions as a service that another plugin
* may use and through the popup menu to the user.
*/
//@formatter:off
@PluginInfo(
@ -89,6 +86,8 @@ public class DisassemblerPlugin extends Plugin {
private DockingAction mips16DisassembleAction;
private DockingAction ppcDisassembleAction;
private DockingAction ppcVleDisassembleAction;
private DockingAction x86_64DisassembleAction;
private DockingAction x86_32DisassembleAction;
private DockingAction setFlowOverrideAction;
/** Dialog for obtaining the processor state to be used for disassembling. */
@ -128,8 +127,7 @@ public class DisassemblerPlugin extends Plugin {
//////////////////////////////////////////////////////////////////////
/**
* Creates a new instance of the plugin giving it the tool that
* it will work in.
* Creates a new instance of the plugin giving it the tool that it will work in.
*/
public DisassemblerPlugin(PluginTool tool) {
super(tool);
@ -177,6 +175,8 @@ public class DisassemblerPlugin extends Plugin {
mips16DisassembleAction = new MipsDisassembleAction(this, GROUP_NAME, true);
ppcDisassembleAction = new PowerPCDisassembleAction(this, GROUP_NAME, false);
ppcVleDisassembleAction = new PowerPCDisassembleAction(this, GROUP_NAME, true);
x86_64DisassembleAction = new X86_64DisassembleAction(this, GROUP_NAME, false);
x86_32DisassembleAction = new X86_64DisassembleAction(this, GROUP_NAME, true);
setFlowOverrideAction = new SetFlowOverrideAction(this, GROUP_NAME);
tool.addAction(disassembleAction);
@ -190,6 +190,8 @@ public class DisassemblerPlugin extends Plugin {
tool.addAction(mips16DisassembleAction);
tool.addAction(ppcDisassembleAction);
tool.addAction(ppcVleDisassembleAction);
tool.addAction(x86_64DisassembleAction);
tool.addAction(x86_32DisassembleAction);
tool.addAction(contextAction);
tool.addAction(setFlowOverrideAction);
}
@ -244,7 +246,8 @@ public class DisassemblerPlugin extends Plugin {
try {
currentProgram.getMemory().getByte(addr);
AddressSetView restrictedSet = null;
if (isDynamicListing) {
// I believe this is deprecated
/*if (isDynamicListing) {
// TODO: should we have option to control restricted range?
Address min, max;
try {
@ -260,7 +263,7 @@ public class DisassemblerPlugin extends Plugin {
max = addr.getAddressSpace().getMaxAddress();
}
restrictedSet = new AddressSet(min, max);
}
}*/
cmd = new DisassembleCommand(addr, restrictedSet, true);
}
catch (MemoryAccessException e) {
@ -409,4 +412,27 @@ public class DisassemblerPlugin extends Plugin {
}
}
public void disassembleX86_64Callback(ListingActionContext context, boolean size32Mode) {
ProgramSelection currentSelection = context.getSelection();
ProgramLocation currentLocation = context.getLocation();
Program currentProgram = context.getProgram();
final X86_64DisassembleCommand cmd;
if ((currentSelection != null) && (!currentSelection.isEmpty())) {
cmd = new X86_64DisassembleCommand(currentSelection, null, size32Mode);
}
else {
Address addr = currentLocation.getAddress();
try {
currentProgram.getMemory().getByte(addr);
cmd = new X86_64DisassembleCommand(addr, null, size32Mode);
}
catch (MemoryAccessException e) {
tool.setStatusInfo("Can't disassemble uninitialized memory!", true);
return;
}
}
tool.executeBackgroundCommand(cmd, currentProgram);
}
}

View File

@ -0,0 +1,80 @@
/* ###
* IP: GHIDRA
*
* 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.
*/
package ghidra.app.plugin.core.disassembler;
import java.awt.event.KeyEvent;
import docking.action.KeyBindingData;
import docking.action.MenuData;
import ghidra.app.context.ListingActionContext;
import ghidra.app.context.ListingContextAction;
import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.Processor;
import ghidra.program.model.listing.Program;
public class X86_64DisassembleAction extends ListingContextAction {
private final DisassemblerPlugin plugin;
private final boolean disassemble32Bit;
public X86_64DisassembleAction(DisassemblerPlugin plugin, String groupName,
boolean disassemble32Bit) {
super("Disassemble " + (disassemble32Bit ? "32" : "64") + "-bit x86", plugin.getName());
this.plugin = plugin;
this.disassemble32Bit = disassemble32Bit;
setPopupMenuData(new MenuData(new String[] { getName() }, null, groupName));
int keyEvent = (disassemble32Bit ? KeyEvent.VK_F12 : KeyEvent.VK_F11);
setKeyBindingData(new KeyBindingData(keyEvent, 0));
}
@Override
public void actionPerformed(ListingActionContext context) {
plugin.disassembleX86_64Callback(context, disassemble32Bit);
}
@Override
public boolean isEnabledForContext(ListingActionContext context) {
// STOPGAP: Disable these in the static context
if (!(context instanceof CodeViewerActionContext)) {
return false;
}
Address address = context.getAddress();
if (address == null) {
return false;
}
Program program = context.getProgram();
Language lang = program.getLanguage();
Processor proc = lang.getProcessor();
/*
* Action only intended for use where 64-bit x86 is available. I'm just going to check for
* x86 with size 64.
*/
if (!"x86".equals(proc.toString())) {
return false;
}
if (lang.getLanguageDescription().getSize() != 64) {
return false;
}
return plugin.checkDisassemblyEnabled(context, address, true);
}
}

View File

@ -7,7 +7,7 @@
}
@ifdef IA64
:ADCX Reg64, rm64 is vexMode=0 & opsize=2 & $(PRE_66) & byte=0x0F; byte=0x38; byte=0xF6; Reg64 ... & rm64 {
:ADCX Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_66) & byte=0x0F; byte=0x38; byte=0xF6; Reg64 ... & rm64 {
tmp:9 = zext(Reg64) + zext(rm64) + zext(CF);
tmpCF:1 = tmp(8); # just the carry byte
CF = tmpCF != 0;
@ -24,7 +24,7 @@
}
@ifdef IA64
:ADOX Reg64, rm64 is vexMode=0 & opsize=2 & $(PRE_F3) & byte=0x0F; byte=0x38; byte=0xF6; Reg64 ... & rm64 {
:ADOX Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_F3) & byte=0x0F; byte=0x38; byte=0xF6; Reg64 ... & rm64 {
tmp:9 = zext(Reg64) + zext(rm64) + zext(OF);
tmpOF:1 = tmp(8); # just the carry byte
OF = tmpOF != 0;

View File

@ -684,7 +684,7 @@ define pcodeop vcvtsd2si_avx ;
# CVTSD2SI 3-253 PAGE 823 LINE 44317
@ifdef IA64
:VCVTSD2SI Reg64, XmmReg2_m64 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_W1); byte=0x2D; Reg64 ... & XmmReg2_m64
:VCVTSD2SI Reg64, XmmReg2_m64 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_W1); byte=0x2D; Reg64 ... & XmmReg2_m64
{
Reg64 = vcvtsd2si_avx( XmmReg2_m64 );
}
@ -710,7 +710,7 @@ define pcodeop vcvtsi2sd_avx ;
# CVTSI2SD 3-257 PAGE 827 LINE 44519
@ifdef IA64
:VCVTSI2SD XmmReg1, vexVVVV_XmmReg, rm64 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x2A; (XmmReg1 & YmmReg1) ... & rm64
:VCVTSI2SD XmmReg1, vexVVVV_XmmReg, rm64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x2A; (XmmReg1 & YmmReg1) ... & rm64
{
local tmp:16 = vcvtsi2sd_avx( vexVVVV_XmmReg, rm64 );
YmmReg1 = zext(tmp);
@ -729,7 +729,7 @@ define pcodeop vcvtsi2ss_avx ;
# CVTSI2SS 3-259 PAGE 829 LINE 44634
@ifdef IA64
:VCVTSI2SS XmmReg1, vexVVVV_XmmReg, rm64 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x2A; (XmmReg1 & YmmReg1) ... & rm64
:VCVTSI2SS XmmReg1, vexVVVV_XmmReg, rm64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x2A; (XmmReg1 & YmmReg1) ... & rm64
{
local tmp:16 = vcvtsi2ss_avx( vexVVVV_XmmReg, rm64 );
YmmReg1 = zext(tmp);
@ -756,7 +756,7 @@ define pcodeop vcvtss2si_avx ;
# CVTSS2SI 3-263 PAGE 833 LINE 44837
@ifdef IA64
:VCVTSS2SI Reg64, XmmReg2_m32 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_W1); byte=0x2D; Reg64 ... & XmmReg2_m32
:VCVTSS2SI Reg64, XmmReg2_m32 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_W1); byte=0x2D; Reg64 ... & XmmReg2_m32
{
Reg64 = vcvtss2si_avx( XmmReg2_m32 );
}
@ -805,7 +805,7 @@ define pcodeop vcvttsd2si_avx ;
# CVTTSD2SI 3-274 PAGE 844 LINE 45382
@ifdef IA64
:VCVTTSD2SI Reg64, XmmReg2_m64 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_W1); byte=0x2C; Reg64 ... & XmmReg2_m64
:VCVTTSD2SI Reg64, XmmReg2_m64 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_W1); byte=0x2C; Reg64 ... & XmmReg2_m64
{
Reg64 = vcvttsd2si_avx( XmmReg2_m64 );
}
@ -821,7 +821,7 @@ define pcodeop vcvttss2si_avx ;
# CVTTSS2SI 3-276 PAGE 846 LINE 45476
@ifdef IA64
:VCVTTSS2SI Reg64, XmmReg2_m32 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_W1); byte=0x2C; Reg64 ... & XmmReg2_m32
:VCVTTSS2SI Reg64, XmmReg2_m32 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_W1); byte=0x2C; Reg64 ... & XmmReg2_m32
{
Reg64 = vcvttss2si_avx( XmmReg2_m32 );
}
@ -1186,7 +1186,7 @@ define pcodeop vmovd_avx ;
# MOVD/MOVQ 4-55 PAGE 1175 LINE 61360
define pcodeop vmovq_avx ;
@ifdef IA64
:VMOVQ XmmReg1, rm64 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1); byte=0x6E; (XmmReg1 & YmmReg1) ... & rm64
:VMOVQ XmmReg1, rm64 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1); byte=0x6E; (XmmReg1 & YmmReg1) ... & rm64
{
local tmp:16 = vmovq_avx( rm64 );
YmmReg1 = zext(tmp);
@ -1202,7 +1202,7 @@ define pcodeop vmovq_avx ;
# MOVD/MOVQ 4-55 PAGE 1175 LINE 61364
@ifdef IA64
:VMOVQ rm64, XmmReg1 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1); byte=0x7E; XmmReg1 ... & rm64
:VMOVQ rm64, XmmReg1 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1); byte=0x7E; XmmReg1 ... & rm64
{
rm64 = vmovq_avx( XmmReg1 );
}
@ -1947,7 +1947,7 @@ define pcodeop vpextrd_avx ;
# PEXTRB/PEXTRD/PEXTRQ 4-274 PAGE 1394 LINE 72330
define pcodeop vpextrq_avx ;
@ifdef IA64
:VPEXTRQ rm64, XmmReg1, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1); byte=0x16; XmmReg1 ... & rm64; imm8
:VPEXTRQ rm64, XmmReg1, imm8 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1); byte=0x16; XmmReg1 ... & rm64; imm8
{
rm64 = vpextrq_avx( XmmReg1, imm8:1 );
}
@ -2052,7 +2052,7 @@ define pcodeop vpinsrd_avx ;
# PINSRB/PINSRD/PINSRQ 4-293 PAGE 1413 LINE 73327
define pcodeop vpinsrq_avx ;
@ifdef IA64
:VPINSRQ XmmReg1, vexVVVV_XmmReg, rm64, imm8 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x22; (XmmReg1 & YmmReg1) ... & rm64; imm8
:VPINSRQ XmmReg1, vexVVVV_XmmReg, rm64, imm8 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x22; (XmmReg1 & YmmReg1) ... & rm64; imm8
{
local tmp:16 = vpinsrq_avx( vexVVVV_XmmReg, rm64, imm8:1 );
YmmReg1 = zext(tmp);

View File

@ -33,7 +33,7 @@ define pcodeop vgatherdpd ;
# VGATHERDPD/VGATHERQPD 5-251 PAGE 2075 LINE 106908
@ifdef IA64
define pcodeop vgatherqpd ;
:VGATHERQPD XmmReg1, q_vm64x, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & q_vm64x {
:VGATHERQPD XmmReg1, q_vm64x, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & q_vm64x {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vgatherqpd(XmmReg1, q_vm64x, vexVVVV_XmmReg);
local tmp:16 = vgatherqpd(XmmReg1, vexVVVV_XmmReg);
@ -54,7 +54,7 @@ define pcodeop vgatherqpd ;
# VGATHERDPD/VGATHERQPD 5-251 PAGE 2075 LINE 106918
@ifdef IA64
:VGATHERQPD YmmReg1, q_vm64y, vexVVVV_YmmReg is $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x93; YmmReg1 ... & q_vm64y {
:VGATHERQPD YmmReg1, q_vm64y, vexVVVV_YmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x93; YmmReg1 ... & q_vm64y {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# YmmReg1 = vgatherqpd(YmmReg1, q_vm64y, vexVVVV_YmmReg);
YmmReg1 = vgatherqpd(YmmReg1, vexVVVV_YmmReg);
@ -78,7 +78,7 @@ define pcodeop vgatherdps ;
# VGATHERDPS/VGATHERQPS 5-256 PAGE 2080 LINE 107135
@ifdef IA64
define pcodeop vgatherqps ;
:VGATHERQPS XmmReg1, d_vm64x, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & d_vm64x {
:VGATHERQPS XmmReg1, d_vm64x, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & d_vm64x {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vgatherqps(XmmReg1, d_vm64x, vexVVVV_XmmReg);
local tmp:16 = vgatherqps(XmmReg1, vexVVVV_XmmReg);
@ -99,7 +99,7 @@ define pcodeop vgatherqps ;
# VGATHERDPS/VGATHERQPS 5-256 PAGE 2080 LINE 107145
@ifdef IA64
:VGATHERQPS XmmReg1, d_vm64y, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & d_vm64y {
:VGATHERQPS XmmReg1, d_vm64y, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & d_vm64y {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vgatherqps(XmmReg1, d_vm64y, vexVVVV_XmmReg);
XmmReg1 = vgatherqps(XmmReg1, vexVVVV_XmmReg);
@ -133,7 +133,7 @@ define pcodeop vpgatherdd ;
# VPGATHERDD/VPGATHERQD 5-273 PAGE 2097 LINE 107888
@ifdef IA64
define pcodeop vpgatherqd ;
:VPGATHERQD XmmReg1, d_vm64x, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & d_vm64x {
:VPGATHERQD XmmReg1, d_vm64x, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & d_vm64x {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vpgatherqd(XmmReg1, d_vm64x, vexVVVV_XmmReg);
local tmp:16 = vpgatherqd(XmmReg1, vexVVVV_XmmReg);
@ -154,7 +154,7 @@ define pcodeop vpgatherqd ;
# VPGATHERDD/VPGATHERQD 5-273 PAGE 2097 LINE 107896
@ifdef IA64
:VPGATHERQD XmmReg1, d_vm64y, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & d_vm64y {
:VPGATHERQD XmmReg1, d_vm64y, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & d_vm64y {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vpgatherqd(XmmReg1, d_vm64y, vexVVVV_XmmReg);
local tmp:16 = vpgatherqd(XmmReg1, vexVVVV_XmmReg);
@ -179,7 +179,7 @@ define pcodeop vpgatherdq ;
# VPGATHERDQ/VPGATHERQQ 5-280 PAGE 2104 LINE 108238
@ifdef IA64
define pcodeop vpgatherqq ;
:VPGATHERQQ XmmReg1, q_vm64x, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & q_vm64x {
:VPGATHERQQ XmmReg1, q_vm64x, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & q_vm64x {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vpgatherqq(XmmReg1, q_vm64x, vexVVVV_XmmReg);
local tmp:16 = vpgatherqq(XmmReg1, vexVVVV_XmmReg);
@ -200,7 +200,7 @@ define pcodeop vpgatherqq ;
# VPGATHERDQ/VPGATHERQQ 5-280 PAGE 2104 LINE 108246
@ifdef IA64
:VPGATHERQQ YmmReg1, q_vm64y, vexVVVV_YmmReg is $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x91; YmmReg1 ... & q_vm64y {
:VPGATHERQQ YmmReg1, q_vm64y, vexVVVV_YmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x91; YmmReg1 ... & q_vm64y {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# YmmReg1 = vpgatherqq(YmmReg1, q_vm64y, vexVVVV_YmmReg);
YmmReg1 = vpgatherqq(YmmReg1, vexVVVV_YmmReg);

View File

@ -21,7 +21,7 @@ macro tzcntflags(input, output) {
@ifdef IA64
# TODO remove ANDN from ia.sinc ?????
:ANDN Reg64, vexVVVV_r64, rm64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf2; Reg64 ... & rm64
:ANDN Reg64, vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf2; Reg64 ... & rm64
{
Reg64 = ~(vexVVVV_r64) & rm64;
resultflags(Reg64);
@ -46,7 +46,7 @@ macro tzcntflags(input, output) {
}
@ifdef IA64
:BEXTR Reg64, rm64, vexVVVV_r64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
:BEXTR Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
{
sourceTmp:1 = vexVVVV_r64[0,8];
lengthTmp:1 = vexVVVV_r64[8,8];
@ -74,7 +74,7 @@ macro tzcntflags(input, output) {
}
@ifdef IA64
:BLSI vexVVVV_r64, rm64 is $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=3 ... & rm64
:BLSI vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=3 ... & rm64
{
vexVVVV_r64 = -rm64 & rm64;
@ -100,7 +100,7 @@ macro tzcntflags(input, output) {
}
@ifdef IA64
:BLSMSK vexVVVV_r64, rm64 is $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=2 ... & rm64
:BLSMSK vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=2 ... & rm64
{
CF = (rm64 == 0);
vexVVVV_r64 = (rm64 - 1) ^ rm64;
@ -126,7 +126,7 @@ macro tzcntflags(input, output) {
}
@ifdef IA64
:BLSR vexVVVV_r64, rm64 is $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=1 ... & rm64
:BLSR vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=1 ... & rm64
{
CF = (rm64 == 0);
vexVVVV_r64 = (rm64 - 1) & rm64;
@ -176,7 +176,7 @@ macro tzcntflags(input, output) {
}
@ifdef IA64
:TZCNT Reg64, rm64 is vexMode=0 & opsize=2 & $(PRE_F3) & $(REX_W) & byte=0x0F; byte=0xBC; Reg64 ... & rm64 {
:TZCNT Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_F3) & $(REX_W) & byte=0x0F; byte=0xBC; Reg64 ... & rm64 {
countTmp:8 = 0;
inputTmp:8 = rm64;

View File

@ -22,7 +22,7 @@
}
@ifdef IA64
:BZHI Reg64, rm64, vexVVVV_r64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
:BZHI Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
{
indexTmp:1 = vexVVVV_r64:1;
@ -52,7 +52,7 @@
}
@ifdef IA64
:MULX Reg64, vexVVVV_r64, rm64 is $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf6; Reg64 ... & rm64
:MULX Reg64, vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf6; Reg64 ... & rm64
{
temp:16 = zext(RDX) * zext(rm64);
@ -85,7 +85,7 @@
}
@ifdef IA64
:PDEP Reg64, vexVVVV_r64, rm64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
:PDEP Reg64, vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
{
sourceTmp:8 = vexVVVV_r64;
@ -128,7 +128,7 @@
}
@ifdef IA64
:PEXT Reg64, vexVVVV_r64, rm64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F3) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
:PEXT Reg64, vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F3) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
{
indexTmp:8 = 0x8000000000000000;
resultTmp:8 = 0;
@ -157,7 +157,7 @@
}
@ifdef IA64
:RORX Reg64, rm64, imm8 is $(VEX_NONE) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F3A) & $(VEX_W1); byte=0xf0; Reg64 ... & rm64; imm8
:RORX Reg64, rm64, imm8 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F3A) & $(VEX_W1); byte=0xf0; Reg64 ... & rm64; imm8
{
shiftTmp:1 = (imm8:1 & 0x3F);
@ -173,7 +173,7 @@
}
@ifdef IA64
:SARX Reg64, rm64, vexVVVV_r64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F3) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
:SARX Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F3) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
{
Reg64 = rm64 s>> (vexVVVV_r64 & 0x000000000000003F);
}
@ -187,7 +187,7 @@
}
@ifdef IA64
:SHLX Reg64, rm64, vexVVVV_r64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
:SHLX Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
{
Reg64 = rm64 << (vexVVVV_r64 & 0x000000000000003F);
}
@ -201,7 +201,7 @@
}
@ifdef IA64
:SHRX Reg64, rm64, vexVVVV_r64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
:SHRX Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
{
Reg64 = rm64 >> (vexVVVV_r64 & 0x000000000000003F);
}

View File

@ -16,7 +16,7 @@ define pcodeop ShadowStackLoad4B;
SSP = SSP + zext(4 * r32:1);
}
@ifdef IA64
:INCSSPQ r64 is vexMode=0 & $(PRE_F3) & $(REX_W) & byte=0x0f; byte=0xae; reg_opcode=5 & r64 {
:INCSSPQ r64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & $(REX_W) & byte=0x0f; byte=0xae; reg_opcode=5 & r64 {
SSP = SSP + zext(8 * r64:1);
}
@endif
@ -25,7 +25,7 @@ define pcodeop ShadowStackLoad4B;
r32 = SSP:4;
}
@ifdef IA64
:RDSSPQ r64 is vexMode=0 & $(PRE_F3) & $(REX_W) & byte=0x0f; byte=0x1e; mod=3 & reg_opcode=1 & r64 {
:RDSSPQ r64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & $(REX_W) & byte=0x0f; byte=0x1e; mod=3 & reg_opcode=1 & r64 {
r64 = SSP;
}
@endif
@ -50,7 +50,7 @@ define pcodeop writeToUserShadowStack;
writeToShadowStack(rm32, Reg32);
}
@ifdef IA64
:WRSSQ rm64,Reg64 is vexMode=0 & $(REX_W) & byte=0x0f; byte=0x0f; byte=0x38; byte=0xf6; rm64 & Reg64 ... {
:WRSSQ rm64,Reg64 is $(LONGMODE_ON) & vexMode=0 & $(REX_W) & byte=0x0f; byte=0x0f; byte=0x38; byte=0xf6; rm64 & Reg64 ... {
writeToShadowStack(rm64, Reg64);
}
@endif
@ -59,7 +59,7 @@ define pcodeop writeToUserShadowStack;
writeToUserShadowStack(rm32, Reg32);
}
@ifdef IA64
:WRUSSQ rm64,Reg64 is vexMode=0 & $(PRE_66) & $(REX_W) & byte=0x0f; byte=0x0f; byte=0x38; byte=0xf5; rm64 & Reg64 ... {
:WRUSSQ rm64,Reg64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & $(REX_W) & byte=0x0f; byte=0x0f; byte=0x38; byte=0xf5; rm64 & Reg64 ... {
writeToUserShadowStack(rm64, Reg64);
}
@endif
@ -78,7 +78,7 @@ define pcodeop clearShadowStackBusy;
:ENDBR32 is vexMode=0 & $(PRE_F3) & (opsize=0 | opsize=1 | opsize=2 | opsize=3) & byte=0x0f; byte=0x1e; byte=0xfb {}
@ifdef IA64
:ENDBR64 is vexMode=0 & $(PRE_F3) & (opsize=0 | opsize=1 | opsize=2 | opsize=3) & byte=0x0f; byte=0x1e; byte=0xfa {}
:ENDBR64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & (opsize=0 | opsize=1 | opsize=2 | opsize=3) & byte=0x0f; byte=0x1e; byte=0xfa {}
@endif

View File

@ -5,7 +5,7 @@ define pcodeop clwb;
@ifdef IA64
define pcodeop clflushopt;
:CLFLUSHOPT m8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xAE; m8 & reg_opcode=7 ... {
:CLFLUSHOPT m8 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xAE; m8 & reg_opcode=7 ... {
clflushopt(m8);
}
@endif

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,7 @@ macro lzcntflags(input, output) {
}
@ifdef IA64
:LZCNT Reg64, rm64 is vexMode=0 & opsize=2 & $(PRE_F3) & $(REX_W) & byte=0x0F; byte=0xBD; Reg64 ... & rm64 {
:LZCNT Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_F3) & $(REX_W) & byte=0x0F; byte=0xBD; Reg64 ... & rm64 {
countTmp:8 = 0;
inputTmp:8 = rm64;

View File

@ -5,7 +5,6 @@ define pcodeop br_exception;
# - if no base register, needs 0
@ifdef IA64
bndmk_addr64: [Rmr64] is mod=0 & Rmr64 { export Rmr64; }
bndmk_addr64: [Rmr64 + simm8_64] is mod=1 & Rmr64; simm8_64 { export Rmr64; }
bndmk_addr64: [simm32_64 + Rmr64] is mod=2 & Rmr64; simm32_64 { export Rmr64; }
@ -24,8 +23,8 @@ bndmk_addr64: [simm32_64 + Base64 + Index64*ss] is mod=2 & r_m=4; Index64 & Base
bndmk_addr64: [simm32_64 + Base64] is mod=2 & r_m=4; rexXprefix=0 & index64=4 & Base64; simm32_64 { export Base64; }
bndmk_addr64: [Base64 + Index64*ss] is mod=2 & r_m=4; Index64 & Base64 & ss; imm32=0 { export Base64; }
bndmk_addr64: [Base64] is mod=2 & r_m=4; rexXprefix=0 & index64=4 & Base64; imm32=0 { export Base64; }
@endif
@else
bndmk_addr32: [Rmr32] is mod=0 & Rmr32 { export Rmr32; }
bndmk_addr32: [Rmr32 + simm8_32] is mod=1 & Rmr32; simm8_32 { export Rmr32; }
bndmk_addr32: [Rmr32] is mod=1 & r_m!=4 & Rmr32; simm8=0 { export Rmr32; }
@ -44,13 +43,12 @@ bndmk_addr32: [imm32 + Base + Index*ss] is mod=2 & r_m=4; Index & Base & ss; i
bndmk_addr32: [imm32 + Base] is mod=2 & r_m=4; index=4 & Base; imm32 { export Base; }
bndmk_addr32: [Base + Index*ss] is mod=2 & r_m=4; Index & Base & ss; imm32=0 { export Base; }
bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export Base; }
@endif
@ifdef IA64
:BNDCL bnd1, Rmr64 is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_lb & Rmr64 {
:BNDCL bnd1, Rmr64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_lb & Rmr64 {
# if (reg < BND.LB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(Rmr64 < bnd1_lb) goto <done>;
BNDSTATUS = 0x01;
@ -58,7 +56,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
<done>
}
:BNDCL bnd1, Mem is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_lb) ... & Mem {
:BNDCL bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_lb) ... & Mem {
# if (LEA(mem) < BND.LB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(Mem < bnd1_lb) goto <done>;
BNDSTATUS = 0x01;
@ -66,7 +64,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
<done>
}
:BNDCU bnd1, Rmr64 is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_ub & Rmr64 {
:BNDCU bnd1, Rmr64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_ub & Rmr64 {
# if (reg > ~(BND.UB)) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(Rmr64 > ~bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
@ -74,7 +72,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
<done>
}
:BNDCU bnd1, Mem is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_ub) ... & Mem {
:BNDCU bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_ub) ... & Mem {
# if (LEA(mem) > ~(BND.UB)) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(Mem > ~bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
@ -82,7 +80,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
<done>
}
:BNDCN bnd1, Rmr64 is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd1_ub & Rmr64 {
:BNDCN bnd1, Rmr64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd1_ub & Rmr64 {
# if (reg > BND.UB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(Rmr64 > bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
@ -90,7 +88,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
<done>
}
:BNDCN bnd1, Mem is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; (bnd1 & bnd1_ub) ... & Mem {
:BNDCN bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; (bnd1 & bnd1_ub) ... & Mem {
# if (LEA(mem) > BND.UB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(Mem > bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
@ -99,7 +97,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
}
#TODO: This probably cannot be fully modeled
:BNDLDX bnd1, Mem is vexMode=0 & byte=0x0F; byte=0x1A; bnd1 ... & Mem {
:BNDLDX bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & byte=0x0F; byte=0x1A; bnd1 ... & Mem {
# BNDSTATUS = bndldx_status( Mem, BNDCFGS, BNDCFGU );
# bnd1 = bndldx( Mem, BNDCFGS, BNDCFGU );
@ -107,30 +105,30 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
bnd1 = *:16 Mem;
}
:BNDMK bnd1, Mem is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & ( bndmk_addr64 & Mem ) {
:BNDMK bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & ( bndmk_addr64 & Mem ) {
# BND.LB and BND.UB set from m64
bnd1_lb = bndmk_addr64;
bnd1_ub = Mem;
}
:BNDMOV bnd1, m128 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; bnd1 ... & m128 {
:BNDMOV bnd1, m128 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; bnd1 ... & m128 {
bnd1 = m128;
}
:BNDMOV bnd1, bnd2 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd2 {
:BNDMOV bnd1, bnd2 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd2 {
bnd1 = bnd2;
}
:BNDMOV m128, bnd1 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; bnd1 ... & m128 {
:BNDMOV m128, bnd1 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; bnd1 ... & m128 {
m128 = bnd1;
}
:BNDMOV bnd2, bnd1 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd2 {
:BNDMOV bnd2, bnd1 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd2 {
bnd2 = bnd1;
}
#TODO: This probably cannot be fully modeled
:BNDSTX Mem, bnd1 is vexMode=0 & byte=0x0F; byte=0x1B; bnd1 ... & Mem {
:BNDSTX Mem, bnd1 is $(LONGMODE_ON) & vexMode=0 & byte=0x0F; byte=0x1B; bnd1 ... & Mem {
# BNDSTATUS = bndstx_status( bnd1, BNDCFGS, BNDCFGU );
# Mem = bndstx( bnd1, BNDCFGS, BNDCFGU );
@ -138,11 +136,9 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
*:16 Mem = bnd1;
}
@endif
@else
:BNDCL bnd1, Rmr32 is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_lb & Rmr32 {
:BNDCL bnd1, Rmr32 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_lb & Rmr32 {
# if (reg < BND.LB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(zext(Rmr32) < bnd1_lb) goto <done>;
BNDSTATUS = 0x01;
@ -150,7 +146,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
<done>
}
:BNDCL bnd1, Mem is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_lb) ... & Mem {
:BNDCL bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_lb) ... & Mem {
# if (LEA(mem) < BND.LB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(zext(Mem) < bnd1_lb) goto <done>;
BNDSTATUS = 0x01;
@ -158,7 +154,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
<done>
}
:BNDCU bnd1, Rmr32 is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_ub & Rmr32 {
:BNDCU bnd1, Rmr32 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_ub & Rmr32 {
# if (reg > ~(BND.UB)) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(zext(Rmr32) > ~bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
@ -166,7 +162,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
<done>
}
:BNDCU bnd1, Mem is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_ub) ... & Mem {
:BNDCU bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_ub) ... & Mem {
# if (LEA(mem) > ~(BND.UB)) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(zext(Mem) > ~bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
@ -174,7 +170,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
<done>
}
:BNDCN bnd1, Rmr32 is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd1_ub & Rmr32 {
:BNDCN bnd1, Rmr32 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd1_ub & Rmr32 {
# if (reg > BND.UB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(zext(Rmr32) > bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
@ -182,7 +178,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
<done>
}
:BNDCN bnd1, Mem is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; (bnd1 & bnd1_ub) ... & Mem {
:BNDCN bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; (bnd1 & bnd1_ub) ... & Mem {
# if (LEA(mem) > BND.UB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(zext(Mem) > bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
@ -191,7 +187,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
}
#TODO: This probably cannot be fully modeled
:BNDLDX bnd1, Mem is vexMode=0 & byte=0x0F; byte=0x1A; ( bnd1 & bnd1_lb & bnd1_ub ) ... & Mem {
:BNDLDX bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & byte=0x0F; byte=0x1A; ( bnd1 & bnd1_lb & bnd1_ub ) ... & Mem {
# BNDSTATUS = bndldx_status( Mem, BNDCFGS, BNDCFGU );
# bnd1 = bndldx( Mem, BNDCFGS, BNDCFGU );
@ -202,33 +198,33 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
bnd1_ub = zext(tmp2);
}
:BNDMK bnd1, Mem is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & ( bndmk_addr32 & Mem ) {
:BNDMK bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & ( bndmk_addr32 & Mem ) {
# BND.LB and BND.UB set from m32
bnd1_lb = zext(bndmk_addr32);
bnd1_ub = zext(Mem);
}
:BNDMOV bnd1, m64 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; ( bnd1 & bnd1_lb & bnd1_ub ) ... & m64 {
:BNDMOV bnd1, m64 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; ( bnd1 & bnd1_lb & bnd1_ub ) ... & m64 {
tmp:8 = m64;
bnd1_lb = zext(tmp:4);
tmp2:4 = tmp(4);
bnd1_ub = zext(tmp2);
}
:BNDMOV bnd1, bnd2 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd2 {
:BNDMOV bnd1, bnd2 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd2 {
bnd1 = bnd2;
}
:BNDMOV m64, bnd1 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & m64 {
:BNDMOV m64, bnd1 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & m64 {
m64 = (zext(bnd1_ub:4) << 32) | zext(bnd1_lb:4);
}
:BNDMOV bnd2, bnd1 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd2 {
:BNDMOV bnd2, bnd1 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd2 {
bnd2 = bnd1;
}
#TODO: This probably cannot be fully modeled
:BNDSTX Mem, bnd1 is vexMode=0 & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & Mem {
:BNDSTX Mem, bnd1 is $(LONGMODE_OFF) & vexMode=0 & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & Mem {
# BNDSTATUS = bndstx_status( bnd1, BNDCFGS, BNDCFGU );
# Mem = bndstx( bnd1, BNDCFGS, BNDCFGU );
@ -236,5 +232,3 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
*:8 Mem = (zext(bnd1_ub:4) << 32) | zext(bnd1_lb:4);
}
@endif

View File

@ -3,5 +3,5 @@ define pcodeop rdrandIsValid;
:RDRAND rm16 is vexMode=0 & opsize=0 & byte=0x0f; byte=0xC7; (rm16 & reg_opcode=6 ...) { rm16 = rdrand(); CF=rdrandIsValid(); }
:RDRAND rm32 is vexMode=0 & opsize=1 & byte=0x0f; byte=0xC7; (rm32 & reg_opcode=6 ...) { rm32 = rdrand(); CF=rdrandIsValid(); }
@ifdef IA64
:RDRAND rm64 is vexMode=0 & opsize=2 & $(REX_W) & byte=0x0f; byte=0xC7; (rm64 & reg_opcode=6 ...) { rm64 = rdrand(); CF=rdrandIsValid(); }
:RDRAND rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(REX_W) & byte=0x0f; byte=0xC7; (rm64 & reg_opcode=6 ...) { rm64 = rdrand(); CF=rdrandIsValid(); }
@endif

View File

@ -3,5 +3,5 @@ define pcodeop rdseedIsValid;
:RDSEED r16 is vexMode=0 & opsize=0 & byte=0x0f; byte=0xC7; r16 & reg_opcode=7 { r16 = rdseed(); CF=rdseedIsValid(); }
:RDSEED r32 is vexMode=0 & opsize=1 & byte=0x0f; byte=0xC7; r32 & reg_opcode=7 { r32 = rdseed(); CF=rdseedIsValid(); }
@ifdef IA64
:RDSEED r64 is vexMode=0 & opsize=2 & $(REX_W) & byte=0x0f; byte=0xC7; r64 & reg_opcode=7 { r64 = rdseed(); CF=rdseedIsValid(); }
:RDSEED r64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(REX_W) & byte=0x0f; byte=0xC7; r64 & reg_opcode=7 { r64 = rdseed(); CF=rdseedIsValid(); }
@endif

View File

@ -12,6 +12,7 @@
<set name="bit64" val="1"/>
<set name="opsize" val="1"/>
<set name="rexprefix" val="0"/>
<set name="longMode" val="1"/>
</context_set>
<tracked_set space="ram">
<set name="DF" val="0"/>